├── CMakeLists.txt ├── COPYING ├── COPYING.libvdeplug4 ├── README.md ├── Uninstall.cmake ├── doc ├── CMakeLists.txt └── howto_create_a_vdeplug_plugin ├── include ├── CMakeLists.txt ├── libvdeplug.h └── libvdeplug_mod.h ├── libvdeplug4 ├── CMakeLists.txt ├── libvdeplug.c ├── libvdeplug_bonding.c ├── libvdeplug_cmd.c ├── libvdeplug_hub.c ├── libvdeplug_macvtap.c ├── libvdeplug_multi.c ├── libvdeplug_netnode.c ├── libvdeplug_netnode.h ├── libvdeplug_null.c ├── libvdeplug_ptp.c ├── libvdeplug_seqpacket.c ├── libvdeplug_switch.c ├── libvdeplug_tap.c ├── libvdeplug_udp.c ├── libvdeplug_vde.c ├── libvdeplug_vxlan.c ├── libvdeplug_vxvde.c ├── libvdestream.c ├── parseparms.c └── vde_hashtable.c ├── libvdeplug4_static ├── CMakeLists.txt └── libvdeplug.c ├── man ├── CMakeLists.txt ├── Makefile ├── dpipe.1 ├── libvdeplug.3 ├── libvdeplug_bonding.1 ├── libvdeplug_cmd.1 ├── libvdeplug_hub.1 ├── libvdeplug_macvtap.1 ├── libvdeplug_multi.1 ├── libvdeplug_null.1 ├── libvdeplug_ptp.1 ├── libvdeplug_switch.1 ├── libvdeplug_tap.1 ├── libvdeplug_udp.1 ├── libvdeplug_vde.1 ├── libvdeplug_vxlan.1 ├── libvdeplug_vxvde.1 ├── vde_close.3 ├── vde_ctlfd.3 ├── vde_datafd.3 ├── vde_open.3 ├── vde_plug.1 ├── vde_recv.3 └── vde_send.3 └── srcvdeplug4 ├── CMakeLists.txt ├── dpipe.c ├── openclosepidfile.c ├── openclosepidfile.h ├── selfsighandler.c ├── selfsighandler.h ├── vde_plug.c ├── vde_plug_iplog.c ├── vde_plug_iplog.h ├── vde_plug_log.c └── vde_plug_log.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(vdeplug4 3 | VERSION 4.0.0 4 | DESCRIPTION "Virtual Distributed Ethernet. Plug your VM directly to the cloud." 5 | HOMEPAGE_URL "https://github.com/rd235/vdeplug4" 6 | LANGUAGES C) 7 | 8 | include(GNUInstallDirs) 9 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic") 10 | include_directories( 11 | ${PROJECT_SOURCE_DIR}/include 12 | ${PROJECT_SOURCE_DIR}/srcvdeplug4 13 | ) 14 | 15 | include(CheckIncludeFile) 16 | set(LIBS_REQUIRED execs) 17 | 18 | foreach(THISLIB IN LISTS LIBS_REQUIRED) 19 | find_library(LIB${THISLIB}_OK ${THISLIB}) 20 | if(NOT LIB${THISLIB}_OK) 21 | message(FATAL_ERROR "library lib${THISLIB} not found") 22 | endif() 23 | endforeach(THISLIB) 24 | 25 | add_subdirectory(libvdeplug4) 26 | add_subdirectory(srcvdeplug4) 27 | add_subdirectory(libvdeplug4_static) 28 | add_subdirectory(include) 29 | add_subdirectory(doc) 30 | add_subdirectory(man) 31 | 32 | add_custom_target(uninstall 33 | "${CMAKE_COMMAND}" -P "${PROJECT_SOURCE_DIR}/Uninstall.cmake") 34 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | Appendix: How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 19yy 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) 19yy name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Library General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vdeplug4 2 | VDE: Virtual Distributed Ethernet. Plug your VM directly to the cloud. 3 | 4 | Vdeplug4 is a new perspective on virtual networking. 5 | 6 | ## hello vxvde world 7 | 8 | Install vdeplug4: 9 | ``` 10 | $ mkdir build 11 | $ cd build 12 | $ cmake .. 13 | $ make 14 | $ sudo make install 15 | ``` 16 | 17 | Start several VM *on different hosts on the same LAN* (IP ttl must be 1). 18 | (VM virtual controllers must have different MAC addresses). 19 | 20 | e.g. kvm: 21 | ``` 22 | kvm .... -net nic,macaddr=52:54:00:11:22:11 -net vde,sock=vxvde:// 23 | kvm .... -net nic,macaddr=52:54:00:11:22:22 -net vde,sock=vxvde:// 24 | kvm .... -net nic,macaddr=52:54:00:11:22:33 -net vde,sock=vxvde:// 25 | kvm .... -net nic,macaddr=52:54:00:11:22:44 -net vde,sock=vxvde:// 26 | kvm .... -net nic,macaddr=52:54:00:11:22:55 -net vde,sock=vxvde:// 27 | ``` 28 | 29 | All the VM will be automagically on the same Virtual LAN. 30 | (similarly, it is possible to add virtualbox, qemu-system-\* and user-mode-linux 31 | VMs). 32 | 33 | It is possible to connect the virtual newtork to a tuntap interface 34 | and manage in this way the routing towards real networks (maybe the Internet). 35 | The command (to run on any host on the LAN) is: 36 | ``` 37 | $ sudo vde_plug vxvde:// tap://mytap 38 | ``` 39 | 40 | The tap can be defined on a remote host: 41 | ``` 42 | $ vde_plug vxvde:// = ssh fqdn.of.remote.host,org vde_plug tap:// 43 | ``` 44 | 45 | ## what is vdeplug4 46 | 47 | This software package includes a modular library (libvdeplug) and some utility tools (vde\_plug and dpipe) 48 | 49 | The new libvdeplug library is backwards compatible with the previous versions (so it is already supported 50 | by qemu, kvm, virtualbox, user-mode-linux, view-os, lwipv6, picotcp and all the other VM or virtual 51 | stacks supporting vde2). 52 | 53 | The new library supports plug-ins so it is open to new developments in vrtual networking. 54 | 55 | Several plug-ins are provided as standard extensions of the library (batteries included): 56 | - vde: connect to legacy vde\_switch (provided by vde2) 57 | - ptp: peer to peer connection between two VM 58 | - tap: connect a VM or a virtual network to 59 | - vxlan: connect vde switches or other vde networks to vxlan 60 | - vxvde: this plug-in implements distributed virtual switches 61 | - udp: udp tunnelling 62 | 63 | The address of a virtual network is defined by a *Virtual Network Locator* (VNL), a string 64 | whose syntax is similar to web URLs. 65 | 66 | examples: 67 | ``` 68 | vxvde://239.1.2.3/ttl=2 69 | tap://mytap 70 | vde:///tmp/myswitch 71 | myplugin://my.syntax/myarg=myvalue 72 | ``` 73 | This latter example will work provided there is a dynamic library named libvdeplug\_myplugin.so 74 | available and accepting the syntax of the parameters after '//' 75 | 76 | Other modules can be added. Vdeplug4 includes the header file and a support library to implement further plugins. 77 | 78 | ## Credits: 79 | 80 | Mattia Biondi largely contibuted to the conversion from autotools to cmake. (2019) 81 | 82 | -------------------------------------------------------------------------------- /Uninstall.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") 3 | 4 | if(NOT EXISTS ${MANIFEST}) 5 | message(FATAL_ERROR "Cannot find install manifest: '${MANIFEST}'") 6 | endif() 7 | 8 | file(STRINGS ${MANIFEST} files) 9 | foreach(file ${files}) 10 | if(EXISTS ${file} OR IS_SYMLINK ${file}) 11 | message(STATUS "Removing: ${file}") 12 | 13 | execute_process( 14 | COMMAND rm -f ${file} 15 | RESULT_VARIABLE retcode 16 | ) 17 | 18 | if(NOT "${retcode}" STREQUAL "0") 19 | message(WARNING "Failed to remove: ${file}") 20 | endif() 21 | endif() 22 | endforeach(file) 23 | -------------------------------------------------------------------------------- /doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | install(FILES howto_create_a_vdeplug_plugin DESTINATION ${CMAKE_INSTALL_DOCDIR}) 4 | -------------------------------------------------------------------------------- /doc/howto_create_a_vdeplug_plugin: -------------------------------------------------------------------------------- 1 | HOW TO CREATE A VDEPLUG PLUGIN 2 | 3 | May 21, 2017 4 | 5 | Renzo Davoli 6 | 7 | This brief document is for developers who aim to add new VDE implementations. 8 | 9 | Vdeplug4 provides a library to implement new plugins: libvdeplug_mod.so: 10 | add: 11 | #include 12 | in your source files and link your objects with: 13 | -l vdeplug_mod 14 | 15 | This library includes three main features: 16 | * The structure needed by libvdeplug to run the specific implementation 17 | functions 18 | * Functions to parse the options in vde_urls. 19 | * A generic hash table for Ethernet packet dispatching 20 | plus some utility functions. 21 | 22 | +++ struct vdeplug_module +++ 23 | A plugin for vdeplug need: 24 | * to have a prefix "libvdeplug_" in its name. "libvdeplug_foo.so" will be 25 | loaded when a program uses a vde_url beginning by "foo://". 26 | Foo will be the name used in the following examples. 27 | * to export a non-static global variable named vdeplug_ops of type 28 | struct vdeplug_module. 29 | struct vdeplug_module vdeplug_ops={ 30 | .vde_open_real=vde_foo_open, 31 | .vde_recv=vde_foo_recv, 32 | .vde_send=vde_foo_send, 33 | .vde_datafd=vde_foo_datafd, 34 | .vde_ctlfd=vde_foo_ctlfd, 35 | .vde_close=vde_foo_close}; 36 | 37 | vde_foo_open returns a pointer to a struct vdeconn. Actually each 38 | module can cast struct vdeconn to an implementation specific structure 39 | provided the first two fields are preserved (i.e. all specific data 40 | will be stored in the unsized field named "data" of struct vdeconn). 41 | 42 | Please note that vde_foo_open receives a copy of the vde_url provided by the 43 | calling program. THe copy is allocated on the stack, so the value can be 44 | safely modified to parse the url but if the string (or part of of it) should be 45 | stored for a later retrieval the contents needs to be duplicated. (do not 46 | store pointers addressing bytes of vde_url). 47 | 48 | vde_foo_recv, vde_foo_send, vde_foo_datafd, vde_foo_ctlfd, vde_foo_close are 49 | the implementation specific function corresponding to those described in 50 | libvdeplug(3) man page. 51 | 52 | +++ vde_url arguments parsing +++ 53 | 54 | libvdeplug_mod library provides two functions: 55 | int vde_parseparms(char *str,struct vdeparms *parms); 56 | int vde_parsepathparms(char *str,struct vdeparms *parms); 57 | The former has been designed for plug-ins which need IP addresses or 58 | fully qualified domain names as parameters. 59 | The latter is specific for plug-ins using pathnames. 60 | 61 | Using vde_parseparms it is possible to parse vde_urls like; 62 | vxvde:// 63 | vxvde://239.0.0.1 64 | vxvde://239.0.0.1/iface=eth0 65 | vxvde://2001:760::1/iface=eth0 66 | vxvde://239.0.0.1/ipv4/iface=eth0 67 | vxvde://vde.mycompany.com/ipv4/iface=eth0 68 | 69 | arguments are separated by slashes and may or may not have values. 70 | 71 | Using vde_parsepathparms it is possible to parse vde_urls like; 72 | vde:// 73 | vde:///tmp/vde.ctl 74 | vde:///tmp/vde.ctl[2] 75 | vde://[3] 76 | vde:///var/run/grpsw[group=grp/port=2] 77 | arguments are provided within square brackets and separated by slashes. 78 | 79 | Both vde_parseparms and vde_parsepathparms require two arguments, the first is 80 | the string to be parsed, the second is an array of struct vdeparms. 81 | A struct vdeparms element is a pair tag, pointer to the value. 82 | When the tag matches, the value is stored using the pointer. 83 | The array must terminate with an empty element {NULL, NULL}. 84 | The return value for both functions is 0 in case of success, -1 in case of error. 85 | 86 | The examples here above of possible values parseable by vde_parseparms can be 87 | processed using the following code. 88 | 89 | char *ipv4str = NULL; 90 | char *ifacestr = "lo"; 91 | struct vdeparms parms[] = { 92 | {"ipv4",&ipv4str}, 93 | {"iface",&ifacestr}, 94 | {NULL, NULL}}; 95 | ... 96 | if (vde_parseparms(vde_url,parms) < 0) 97 | .... error management 98 | 99 | after vde_parseparms completion vde_url contains the IP address or fully qualified domain name 100 | without the options, ipv4str points to a NULL string (but it is not null) if "ipv4" 101 | is one of the url arguments, and if the argument "iface=eth0" is present ifacestr points to 102 | "eth0" (the seventh char of the argument itself). It is possible to assign default values. 103 | In the example above ifacestr is "lo" if no "iface=something" argument is present. 104 | Please note that each argument-key can occur just once (otherwise the second value overwrites 105 | the first) 106 | 107 | The examples of vde_parsepathparms values can be processed using the following code: 108 | char *portstr = "0"; 109 | char *groupstr = NULL; 110 | struct vdeparms parms[] = { 111 | {"",&port}, 112 | {"port",&portstr}, 113 | {"group",&groupstr}, 114 | {NULL, NULL}}; 115 | ... 116 | if (vde_parsepathparms(vde_url,parms) < 0) 117 | .... error management 118 | 119 | after vde_parsepathparms completion vde_url contains the path only (without square brackets 120 | and arguments). Like vde_parseparms, portstr and groupstr point to the value after 121 | "port=" or "group=" arguments, respectively. 122 | If the first struct vdeparms has an empty string as its key (only for vde_parsepathparms) it gets 123 | the arguments not matching any other key. 124 | It means in this case that: 125 | vde:///tmp/vde.ctl[2] 126 | vde:///tmp/vde.ctl[port=2] 127 | have the same meaning. 128 | 129 | Examples of arguments managements can be found in libvdeplug_*.so in the libvdeplug4 130 | of the source tree of vdeplug4. 131 | 132 | +++ A generic hash table for Ethernet packet dispatching +++ 133 | 134 | Given that VDE handles ethernet packets many plugins need a hash table to 135 | dispatch ethernet packets. 136 | 137 | The key of the dispatching table is the pair (MAC address, VLAN number), the corrisponding 138 | value (the payload) changes depending upon the implementation of VDE (a local switch 139 | may use an integer like a file descriptor or a port number while distributed implementations 140 | like vxvde use socket address, like sockaddr_in or sockaddr_in6). 141 | 142 | The macro to create a hash table is: 143 | struct vde_hashtable *vde_hash_init(type, unsigned int hashsize, unsigned int seed) 144 | where type is the type of the payload, hashsize is the number of element of the 145 | hash table and seed is an optional value to perturbate the hash function computation 146 | in case too many collisions occur. 147 | vde_hash_init returns a descriptor of the hash table which will be used as the first argument 148 | of all the other functions. 149 | 150 | void vde_hash_fini(struct vde_hashtable *table); 151 | deallocate the hash table. 152 | 153 | void vde_find_in_hash_update(struct vde_hashtable *table, unsigned char *src, int vlan, void *payload, time_t now); 154 | This function should be used when a packet is reeceived to update (or renew) the hash entry 155 | for this source of ethernet packets. 156 | The payload (shich should be a pointer to the type specified in vde_hash_fini) is copied 157 | in the hash table and the value now is the (new) timestamp of this match. 158 | 159 | void *vde_find_in_hash(struct vde_hashtable *table, unsigned char *dst, int vlan, time_t too_old); 160 | this function searches in the hash table the destination address. If the entry exists but it 161 | has a timestamp older than the value of the parameter too_old, it is ignored. 162 | So the return value is NULL if the key does not exist or its match validity has expired 163 | otherwise it is a pointer to the payload corresponding to the key. 164 | 165 | void vde_hash_delete(struct vde_hashtable *table, void *payload); 166 | this function deletes an element from the hash table. 167 | 168 | +++ utility functions +++ 169 | unsigned long long strtoullm(const char *numstr); 170 | converts a string in a unsigned long long value (like strtoull). This functions allows 171 | multipliers like K, M, G, T meaning kilo, mega, giga, tera. 172 | e.g. "1K" is converted to 1024. 173 | 174 | gid_t vde_grnam2gid(const char *name); 175 | gets the gid of a group given its name. It returns -1 if such a group does not exist. 176 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | set_target_properties(vdeplug PROPERTIES PUBLIC_HEADER libvdeplug.h) 4 | set_target_properties(vdeplug_mod PROPERTIES PUBLIC_HEADER libvdeplug_mod.h) 5 | 6 | install( 7 | TARGETS vdeplug vdeplug_mod 8 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 9 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 10 | ) 11 | -------------------------------------------------------------------------------- /include/libvdeplug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2006 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #ifndef _VDELIB_H 21 | #define _VDELIB_H 22 | #include 23 | #define LIBVDEPLUG_INTERFACE_VERSION 1 24 | #define VDE_MAXMTU 9216 25 | #define VDE_ETHBUFSIZE (VDE_MAXMTU + 14 + 4) // + Ethernet header + 802.1Q header 26 | 27 | struct vdeconn; 28 | 29 | typedef struct vdeconn VDECONN; 30 | 31 | /* Open a VDE connection. 32 | * vde_open_options: 33 | * port: connect to a specific port of the switch (0=any) 34 | * group: change the ownership of the communication port to a specific group 35 | * (NULL=no change) 36 | * mode: set communication port mode (if 0 standard socket mode applies) 37 | */ 38 | struct vde_open_args { 39 | int port; 40 | char *group; 41 | mode_t mode; 42 | }; 43 | 44 | /* vde_open args: 45 | * vnl: virtual network locator (module://parameters or path) 46 | * e.g. vde:// vde:///var/run/vde.ctl vxvde:// tap://tap0 47 | * descr: description (it will appear in the port description on the switch) 48 | */ 49 | #define vde_open(vnl,descr,open_args) \ 50 | vde_open_real((vnl),(descr),LIBVDEPLUG_INTERFACE_VERSION,(open_args)) 51 | VDECONN *vde_open_real(char *vnl,char *descr,int interface_version, 52 | struct vde_open_args *open_args); 53 | 54 | ssize_t vde_recv(VDECONN *conn,void *buf,size_t len,int flags); 55 | 56 | ssize_t vde_send(VDECONN *conn,const void *buf,size_t len,int flags); 57 | 58 | /* for select/poll when this fd receive data, there are packets to recv 59 | * (call vde_recv) */ 60 | int vde_datafd(VDECONN *conn); 61 | 62 | /* for select/poll. the ctl socket is silent after the initial handshake. 63 | * when EOF the switch has closed the connection */ 64 | int vde_ctlfd(VDECONN *conn); 65 | 66 | int vde_close(VDECONN *conn); 67 | 68 | /* vdestream */ 69 | 70 | struct vdestream; 71 | 72 | typedef struct vdestream VDESTREAM; 73 | 74 | #define PACKET_LENGTH_ERROR 1 75 | 76 | VDESTREAM *vdestream_open(void *opaque, 77 | int fdout, 78 | ssize_t (*frecv)(void *opaque, void *buf, size_t count), 79 | void (*ferr)(void *opaque, int type, char *format, ...) 80 | ); 81 | 82 | ssize_t vdestream_send(VDESTREAM *vdestream, const void *buf, size_t len); 83 | 84 | void vdestream_recv(VDESTREAM *vdestream, unsigned char *buf, size_t len); 85 | 86 | void vdestream_close(VDESTREAM *vdestream); 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /include/libvdeplug_mod.h: -------------------------------------------------------------------------------- 1 | #ifndef VDE_PLUG_H 2 | #define VDE_PLUG_H 3 | 4 | #define MAXDESCR 128 5 | #define CONNECTED_P2P 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | struct vdeplug_module; 12 | struct vdeconn { 13 | void *handle; 14 | struct vdeplug_module *module; 15 | unsigned char data[]; 16 | }; 17 | 18 | struct vdeplug_module { 19 | int flags; 20 | VDECONN *(* vde_open_real)(char *given_vde_url, char *descr,int interface_version, 21 | struct vde_open_args *open_args); 22 | ssize_t (* vde_recv)(VDECONN *conn,void *buf,size_t len,int flags); 23 | ssize_t (* vde_send)(VDECONN *conn,const void *buf,size_t len,int flags); 24 | int (* vde_datafd)(VDECONN *conn); 25 | int (* vde_ctlfd)(VDECONN *conn); 26 | int (* vde_close)(VDECONN *conn); 27 | }; 28 | 29 | struct vdeparms { 30 | char *tag; 31 | char **value; 32 | }; 33 | 34 | int vde_parseparms(char *str,struct vdeparms *parms); 35 | int vde_parsepathparms(char *str,struct vdeparms *parms); 36 | char *vde_parsenestparms(char *str); 37 | 38 | struct vde_hashtable; 39 | void *vde_find_in_hash(struct vde_hashtable *table, unsigned char *dst, int vlan, time_t too_old); 40 | void vde_find_in_hash_update(struct vde_hashtable *table, unsigned char *src, int vlan, void *payload, time_t now); 41 | void vde_hash_delete(struct vde_hashtable *table, void *payload); 42 | #define vde_hash_init(type, hashsize, seed) _vde_hash_init(sizeof(type), (hashsize), (seed)) 43 | struct vde_hashtable *_vde_hash_init(size_t payload_size, unsigned int hashsize, uint64_t seed); 44 | void vde_hash_fini(struct vde_hashtable *table); 45 | 46 | unsigned long long strtoullm(const char *numstr); 47 | 48 | gid_t vde_grnam2gid(const char *name); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /libvdeplug4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | set(VDEPLUG_SOVERSION 2) 4 | add_library(vdeplug SHARED libvdeplug.c libvdestream.c) 5 | set_target_properties(vdeplug PROPERTIES VERSION ${PROJECT_VERSION} 6 | SOVERSION ${VDEPLUG_SOVERSION}) 7 | target_link_libraries(vdeplug -ldl) 8 | target_link_libraries(vdeplug -export-dynamic) 9 | 10 | add_library(vdeplug_mod SHARED parseparms.c vde_hashtable.c) 11 | set_target_properties(vdeplug_mod PROPERTIES VERSION ${PROJECT_VERSION} 12 | SOVERSION ${VDEPLUG_SOVERSION}) 13 | target_link_libraries(vdeplug_mod -ldl) 14 | target_link_libraries(vdeplug_mod -export-dynamic) 15 | 16 | add_library(vdeplug_vde SHARED libvdeplug_vde.c) 17 | target_link_libraries(vdeplug_vde vdeplug_mod) 18 | 19 | add_library(vdeplug_ptp SHARED libvdeplug_ptp.c) 20 | target_link_libraries(vdeplug_ptp vdeplug_mod) 21 | 22 | add_library(vdeplug_tap SHARED libvdeplug_tap.c) 23 | target_link_libraries(vdeplug_tap vdeplug_mod) 24 | 25 | add_library(vdeplug_udp SHARED libvdeplug_udp.c) 26 | target_link_libraries(vdeplug_udp vdeplug_mod) 27 | 28 | add_library(vdeplug_vxlan SHARED libvdeplug_vxlan.c) 29 | target_link_libraries(vdeplug_vxlan vdeplug_mod) 30 | 31 | add_library(vdeplug_vxvde SHARED libvdeplug_vxvde.c) 32 | target_link_libraries(vdeplug_vxvde vdeplug_mod) 33 | 34 | add_library(vdeplug_cmd SHARED libvdeplug_cmd.c) 35 | target_link_libraries(vdeplug_cmd vdeplug_mod -lexecs) 36 | 37 | add_library(vdeplug_null SHARED libvdeplug_null.c) 38 | target_link_libraries(vdeplug_null vdeplug_mod) 39 | 40 | add_library(vdeplug_hub SHARED libvdeplug_hub.c libvdeplug_netnode.c) 41 | target_link_libraries(vdeplug_hub vdeplug_mod) 42 | 43 | add_library(vdeplug_switch SHARED libvdeplug_switch.c libvdeplug_netnode.c) 44 | target_link_libraries(vdeplug_switch vdeplug_mod) 45 | 46 | add_library(vdeplug_multi SHARED libvdeplug_multi.c libvdeplug_netnode.c) 47 | target_link_libraries(vdeplug_multi vdeplug_mod) 48 | 49 | add_library(vdeplug_bonding SHARED libvdeplug_bonding.c libvdeplug_netnode.c) 50 | target_link_libraries(vdeplug_bonding vdeplug_mod) 51 | 52 | add_library(vdeplug_seqpacket SHARED libvdeplug_seqpacket.c) 53 | target_link_libraries(vdeplug_seqpacket vdeplug_mod) 54 | 55 | add_library(vdeplug_macvtap SHARED libvdeplug_macvtap.c) 56 | target_link_libraries(vdeplug_macvtap vdeplug_mod) 57 | 58 | install( 59 | TARGETS vdeplug_mod vdeplug 60 | LIBRARY 61 | DESTINATION ${CMAKE_INSTALL_LIBDIR} 62 | ) 63 | 64 | install( 65 | TARGETS vdeplug_vde vdeplug_ptp vdeplug_tap 66 | vdeplug_udp vdeplug_vxlan vdeplug_vxvde vdeplug_cmd 67 | vdeplug_null vdeplug_hub vdeplug_switch vdeplug_multi 68 | vdeplug_bonding vdeplug_seqpacket vdeplug_macvtap 69 | LIBRARY 70 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/vdeplug 71 | ) 72 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #define _GNU_SOURCE 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "libvdeplug_mod.h" 32 | 33 | /* Per-User standard switch definition */ 34 | /* This will be prefixed by getenv("HOME") */ 35 | /* it can be a symbolic link to the switch dir */ 36 | #define STDSWITCH "/.vdeplug/default" 37 | #define OLDSTDSWITCH "/.vde2/default.switch" 38 | 39 | #define STD_LIB_PATH "/lib:/usr/lib" 40 | #define LIBVDEPLUG "libvdeplug_" 41 | #define LIBVDEPLUGIN "/vdeplug/" LIBVDEPLUG 42 | 43 | #define DEFAULT_MODULE "vde" 44 | uint64_t __vde_version_tag = 4; 45 | 46 | struct vde_open_parms { 47 | char *vde_args; 48 | char *descr; 49 | int interface_version; 50 | struct vde_open_args *open_args; 51 | }; 52 | 53 | static VDECONN *vde_open_module_lib(char *filename, struct vde_open_parms *parms) { 54 | void *handle=dlopen(filename, RTLD_NOW | RTLD_DEEPBIND); 55 | 56 | //printf("TRY %s %s\n", filename, parms->vde_args); 57 | if (handle) { 58 | struct vdeplug_module *module=dlsym(handle, "vdeplug_ops"); 59 | if (module) { 60 | VDECONN *rv = module->vde_open_real(parms->vde_args, parms->descr, parms->interface_version, parms->open_args); 61 | if (rv) { 62 | rv->handle = handle; 63 | rv->module = module; 64 | return rv; 65 | } 66 | } else 67 | errno = EPROTONOSUPPORT; 68 | dlclose(handle); 69 | } else 70 | errno = EPROTONOSUPPORT; 71 | return NULL; 72 | } 73 | 74 | static VDECONN *vde_open_samedir(char *modname, char *subdir, struct vde_open_parms *parms) { 75 | char path[PATH_MAX]; 76 | Dl_info info; 77 | if (dladdr(&__vde_version_tag, &info) != 0) { 78 | const char *libpath = info.dli_fname; 79 | char *slash = strrchr(libpath, '/'); 80 | if (slash) { 81 | int len = slash - libpath; 82 | snprintf(path, PATH_MAX, "%*.*s%s%s.so", 83 | len, len, libpath, subdir, modname); 84 | return vde_open_module_lib(path, parms); 85 | } 86 | } 87 | return errno = EPROTONOSUPPORT, NULL; 88 | } 89 | 90 | static VDECONN *vde_open_dirlist(char *modname, char *dirlist, char *subdir, struct vde_open_parms *parms) { 91 | char path[PATH_MAX]; 92 | VDECONN *retval; 93 | if (dirlist) { 94 | while (*dirlist != 0) { 95 | int len = strchrnul(dirlist, ':') - dirlist; 96 | snprintf(path, PATH_MAX, "%*.*s%s%s.so", 97 | len, len, dirlist, subdir, modname); 98 | retval = vde_open_module_lib(path, parms); 99 | if (retval != NULL || errno != EPROTONOSUPPORT) 100 | return retval; 101 | dirlist += len + (dirlist[len] == ':'); 102 | } 103 | } 104 | return errno = EPROTONOSUPPORT, NULL; 105 | } 106 | 107 | static VDECONN *vde_open_default(char *modname, struct vde_open_parms *parms) { 108 | char path[PATH_MAX]; 109 | snprintf(path, PATH_MAX, LIBVDEPLUG "%s.so", modname); 110 | return vde_open_module_lib(path, parms); 111 | } 112 | 113 | static VDECONN *vde_open_module(char *modname, struct vde_open_parms *parms) { 114 | char *vdeplugin_path = getenv("VDEPLUGIN_PATH"); 115 | // creata a copy of parms->vde_args 116 | size_t vde_args_len = strlen(parms->vde_args); 117 | char vde_args_copy[vde_args_len + 1]; 118 | strcpy(vde_args_copy, parms->vde_args); 119 | parms->vde_args = vde_args_copy; 120 | 121 | // if VDEPLUGIN_PATH exists it defines the search path for plugins 122 | if (vdeplugin_path) 123 | return vde_open_dirlist(modname, vdeplugin_path, "/" LIBVDEPLUG, parms); 124 | else { 125 | VDECONN *retval; 126 | retval = vde_open_samedir(modname, LIBVDEPLUGIN, parms); 127 | if (retval != NULL || errno != EPROTONOSUPPORT) return retval; 128 | retval = vde_open_samedir(modname, "/" LIBVDEPLUG, parms); 129 | if (retval != NULL || errno != EPROTONOSUPPORT) return retval; 130 | retval = vde_open_dirlist(modname, getenv("LD_LIBRARY_PATH"), LIBVDEPLUGIN, parms); 131 | if (retval != NULL || errno != EPROTONOSUPPORT) return retval; 132 | retval = vde_open_dirlist(modname, STD_LIB_PATH, LIBVDEPLUGIN, parms); 133 | if (retval != NULL || errno != EPROTONOSUPPORT) return retval; 134 | return vde_open_default(modname, parms); 135 | } 136 | } 137 | 138 | static void set_newdescr(const char *descr, char *newdescr, size_t newdescrlen) { 139 | char *ssh_client = getenv("SSH_CLIENT"); 140 | int pid = getpid(); 141 | uid_t uid = geteuid(); 142 | FILE *f = fmemopen(newdescr, newdescrlen, "w"); 143 | 144 | fprintf(f, "%s ", descr); 145 | 146 | fprintf(f, "user=%d", uid); 147 | fprintf(f, " pid=%d", pid); 148 | 149 | if (ssh_client) { 150 | int len = strchrnul(ssh_client,' ') - ssh_client; 151 | fprintf(f, " SSH=%*.*s", len, len, ssh_client); 152 | } 153 | 154 | fclose(f); 155 | newdescr[newdescrlen - 1] = 0; 156 | //printf("%s %d\n", newdescr, bufsize); 157 | } 158 | 159 | VDECONN *vde_open_real(char *vde_url, char *descr, int interface_version, 160 | struct vde_open_args *open_args) 161 | { 162 | char std_vde_url[PATH_MAX]; 163 | struct stat statbuf; 164 | char newdescr[MAXDESCR]; 165 | char *tag; 166 | struct vde_open_parms parms = { 167 | .descr = newdescr, 168 | .interface_version = interface_version, 169 | .open_args = open_args 170 | }; 171 | 172 | if (vde_url == NULL) 173 | vde_url = ""; 174 | 175 | tag = strstr(vde_url, "://"); 176 | 177 | set_newdescr(descr, newdescr, MAXDESCR); 178 | 179 | if (tag == NULL) { 180 | if (*vde_url == '\0') { 181 | char *homedir = getenv("HOME"); 182 | if (homedir) { 183 | snprintf(std_vde_url, PATH_MAX, "%s%s", homedir, STDSWITCH); 184 | if (lstat(std_vde_url, &statbuf) >= 0) 185 | vde_url = std_vde_url; 186 | else { 187 | snprintf(std_vde_url, PATH_MAX, "%s%s", homedir, OLDSTDSWITCH); 188 | if (lstat(std_vde_url, &statbuf) >= 0) 189 | vde_url = std_vde_url; 190 | } 191 | } 192 | } 193 | if (stat(vde_url, &statbuf) >= 0) { 194 | if (S_ISREG(statbuf.st_mode)) { 195 | FILE *f=fopen(vde_url,"r"); 196 | if (f != NULL) { 197 | if (fgets(std_vde_url, PATH_MAX, f) != NULL) { 198 | std_vde_url[strlen(std_vde_url) - 1] = 0; 199 | vde_url = std_vde_url; 200 | } 201 | tag = strstr(vde_url, "://"); 202 | fclose(f); 203 | } 204 | } 205 | } 206 | } 207 | if (vde_url == NULL || tag == NULL) { 208 | parms.vde_args = vde_url; 209 | return vde_open_module(DEFAULT_MODULE, &parms); 210 | } else { 211 | int modlen=tag - vde_url; 212 | char modname[modlen + 1]; 213 | snprintf(modname, modlen + 1, "%*.*s", modlen, modlen, vde_url); 214 | parms.vde_args = vde_url + (modlen + 3); 215 | return vde_open_module(modname, &parms); 216 | } 217 | } 218 | 219 | ssize_t vde_recv(VDECONN *conn,void *buf,size_t len,int flags) 220 | { 221 | if (__builtin_expect(conn!=0,1)) 222 | return conn->module->vde_recv(conn,buf,len,flags); 223 | else { 224 | errno=EBADF; 225 | return -1; 226 | } 227 | } 228 | 229 | ssize_t vde_send(VDECONN *conn,const void *buf,size_t len,int flags) 230 | { 231 | if (__builtin_expect(conn!=0,1)) 232 | return conn->module->vde_send(conn,buf,len,flags); 233 | else { 234 | errno=EBADF; 235 | return -1; 236 | } 237 | } 238 | 239 | int vde_datafd(VDECONN *conn) 240 | { 241 | if (__builtin_expect(conn!=0,1)) 242 | return conn->module->vde_datafd(conn); 243 | else { 244 | errno=EBADF; 245 | return -1; 246 | } 247 | } 248 | 249 | int vde_ctlfd(VDECONN *conn) 250 | { 251 | if (__builtin_expect(conn!=0,1)) 252 | return conn->module->vde_ctlfd(conn); 253 | else { 254 | errno=EBADF; 255 | return -1; 256 | } 257 | } 258 | 259 | int vde_close(VDECONN *conn) 260 | { 261 | if (__builtin_expect(conn!=0,1)) { 262 | void *handle=conn->handle; 263 | /* vde_close frees the struct conn */ 264 | int rv=conn->module->vde_close(conn); 265 | if (rv==0) dlclose(handle); 266 | return rv; 267 | } else { 268 | errno=EBADF; 269 | return -1; 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_bonding.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include "libvdeplug_netnode.h" 21 | 22 | struct vdeplug_module vdeplug_ops; 23 | 24 | static __attribute__ ((constructor)) void __init__(void) { 25 | vdeplug_ops = vdeplug_bonding_ops; 26 | } 27 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_cmd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2017 Renzo Davoli, University of Bologna 4 | * 5 | * Stream vde to a command 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation version 2.1 of the License, or (at 10 | * your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "libvdeplug_mod.h" 38 | 39 | static VDECONN *vde_cmd_open(char *given_vde_url, char *descr,int interface_version, 40 | struct vde_open_args *open_args); 41 | static ssize_t vde_cmd_recv(VDECONN *conn,void *buf,size_t len,int flags); 42 | static ssize_t vde_cmd_send(VDECONN *conn,const void *buf,size_t len,int flags); 43 | static int vde_cmd_datafd(VDECONN *conn); 44 | static int vde_cmd_ctlfd(VDECONN *conn); 45 | static int vde_cmd_close(VDECONN *conn); 46 | 47 | struct vdeplug_module vdeplug_ops={ 48 | .vde_open_real=vde_cmd_open, 49 | .vde_recv=vde_cmd_recv, 50 | .vde_send=vde_cmd_send, 51 | .vde_datafd=vde_cmd_datafd, 52 | .vde_ctlfd=vde_cmd_ctlfd, 53 | .vde_close=vde_cmd_close}; 54 | 55 | struct vde_cmd_conn { 56 | void *handle; 57 | struct vdeplug_module *module; 58 | char *cmdstring; 59 | pid_t cmd_pid; 60 | int cmd_fd[2]; 61 | }; 62 | 63 | static VDECONN *vde_cmd_open(char *cmdstring, char *descr,int interface_version, 64 | struct vde_open_args *open_args) 65 | { 66 | struct vde_cmd_conn *newconn; 67 | 68 | if ((newconn=calloc(1,sizeof(struct vde_cmd_conn)))==NULL) 69 | { 70 | errno=ENOMEM; 71 | goto abort; 72 | } 73 | newconn->cmdstring = strdup(cmdstring); 74 | if ((newconn->cmd_pid = coprocsp(cmdstring, newconn->cmd_fd)) < 0) 75 | goto free_abort; 76 | return (VDECONN *)newconn; 77 | free_abort: 78 | free(newconn); 79 | 80 | abort: 81 | return NULL; 82 | } 83 | 84 | static ssize_t vde_cmd_recv(VDECONN *conn,void *buf,size_t len,int flags) 85 | { 86 | struct vde_cmd_conn *vde_conn = (struct vde_cmd_conn *)conn; 87 | unsigned char header[2]; 88 | unsigned int pktlen; 89 | ssize_t rv; 90 | struct pollfd pollok = {vde_conn->cmd_fd[0], POLLIN, 0}; 91 | if ((rv = read(vde_conn->cmd_fd[0], header, 2)) != 2) 92 | goto error; 93 | pktlen = (header[0]<<8) + header[1]; 94 | if (pktlen > VDE_ETHBUFSIZE) 95 | goto error; 96 | if (poll(&pollok,1,0) <= 0) 97 | goto error; 98 | if (pktlen <= len) { 99 | if ((rv = read(vde_conn->cmd_fd[0], buf, pktlen)) != pktlen) 100 | goto error; 101 | return rv; 102 | } else { 103 | ssize_t taillen = pktlen - len; 104 | unsigned char tail[taillen]; 105 | struct iovec iov[2]={{buf, len}, {tail, taillen}}; 106 | if ((rv = readv(vde_conn->cmd_fd[0], iov, 2)) != pktlen) 107 | goto error; 108 | return len; 109 | } 110 | error: 111 | if (rv < 0) { 112 | return rv; 113 | } else if (rv == 0) { // the command terminated 114 | int fd[2]; 115 | int status; 116 | pipe(fd); 117 | dup2(fd[0], vde_conn->cmd_fd[0]); 118 | dup2(fd[1], vde_conn->cmd_fd[1]); 119 | waitpid(vde_conn->cmd_pid, &status, WNOHANG); /* discard exit status */ 120 | fprintf(stderr, "VDE terminated: cmd://%s\n",vde_conn->cmdstring); 121 | return rv; 122 | } else { 123 | errno = EAGAIN; 124 | return 1; 125 | } 126 | } 127 | 128 | static ssize_t vde_cmd_send(VDECONN *conn,const void *buf,size_t len,int flags) 129 | { 130 | struct vde_cmd_conn *vde_conn = (struct vde_cmd_conn *)conn; 131 | if (len <= VDE_ETHBUFSIZE) { 132 | unsigned char header[2]; 133 | struct iovec iov[2]={{header,2},{(void *)buf,len}}; 134 | header[0]=len >> 8; 135 | header[1]=len & 0xff; 136 | return writev(vde_conn->cmd_fd[1],iov,2); 137 | } else 138 | return 0; 139 | } 140 | 141 | static int vde_cmd_datafd(VDECONN *conn) 142 | { 143 | struct vde_cmd_conn *vde_conn = (struct vde_cmd_conn *)conn; 144 | return vde_conn->cmd_fd[0]; 145 | } 146 | 147 | static int vde_cmd_ctlfd(VDECONN *conn) 148 | { 149 | return -1; 150 | } 151 | 152 | static int vde_cmd_close(VDECONN *conn) 153 | { 154 | struct vde_cmd_conn *vde_conn = (struct vde_cmd_conn *)conn; 155 | int status; 156 | close(vde_conn->cmd_fd[1]); 157 | close(vde_conn->cmd_fd[0]); 158 | kill(SIGTERM, vde_conn->cmd_pid); 159 | waitpid(vde_conn->cmd_pid, &status, 0); /* discard exit status */ 160 | if (vde_conn->cmdstring) 161 | free(vde_conn->cmdstring); 162 | free(vde_conn); 163 | return 0; 164 | } 165 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_hub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include "libvdeplug_netnode.h" 21 | 22 | struct vdeplug_module vdeplug_ops; 23 | 24 | static __attribute__ ((constructor)) void __init__(void) { 25 | vdeplug_ops = vdeplug_hub_ops; 26 | } 27 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_macvtap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "libvdeplug_mod.h" 28 | #include 29 | #include 30 | #include 31 | 32 | static VDECONN *vde_macvtap_open(char *given_vde_url, char *descr,int interface_version, 33 | struct vde_open_args *open_args); 34 | static ssize_t vde_macvtap_recv(VDECONN *conn,void *buf,size_t len,int flags); 35 | static ssize_t vde_macvtap_send(VDECONN *conn,const void *buf,size_t len,int flags); 36 | static int vde_macvtap_datafd(VDECONN *conn); 37 | static int vde_macvtap_ctlfd(VDECONN *conn); 38 | static int vde_macvtap_close(VDECONN *conn); 39 | 40 | struct vdeplug_module vdeplug_ops={ 41 | .vde_open_real=vde_macvtap_open, 42 | .vde_recv=vde_macvtap_recv, 43 | .vde_send=vde_macvtap_send, 44 | .vde_datafd=vde_macvtap_datafd, 45 | .vde_ctlfd=vde_macvtap_ctlfd, 46 | .vde_close=vde_macvtap_close}; 47 | 48 | struct vde_macvtap_conn { 49 | void *handle; 50 | struct vdeplug_module *module; 51 | int fddata; 52 | }; 53 | 54 | static VDECONN *vde_macvtap_open(char *given_vde_url, char *descr, int interface_version, 55 | struct vde_open_args *open_args) 56 | { 57 | struct ifreq ifr; 58 | int fddata=-1; 59 | struct vde_macvtap_conn *newconn; 60 | int ifindex = if_nametoindex(given_vde_url); 61 | if (ifindex == 0) 62 | return NULL; 63 | size_t tap_path_len = snprintf(NULL, 0, "/dev/tap%d", ifindex) + 1; 64 | char tap_path[tap_path_len]; 65 | snprintf(tap_path, tap_path_len, "/dev/tap%d", ifindex); 66 | 67 | if((fddata = open(tap_path, O_RDWR)) < 0) 68 | goto abort; 69 | 70 | memset(&ifr, 0, sizeof(ifr)); 71 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 72 | if(ioctl(fddata, TUNSETIFF, (void *) &ifr) < 0) 73 | goto abort; 74 | 75 | if ((newconn=calloc(1,sizeof(struct vde_macvtap_conn)))==NULL) { 76 | errno=ENOMEM; 77 | goto abort; 78 | } 79 | 80 | newconn->fddata=fddata; 81 | 82 | return (VDECONN *)newconn; 83 | 84 | abort: 85 | if (fddata >= 0) close(fddata); 86 | return NULL; 87 | } 88 | 89 | static ssize_t vde_macvtap_recv(VDECONN *conn,void *buf,size_t len,int flags) 90 | { 91 | struct vde_macvtap_conn *vde_conn = (struct vde_macvtap_conn *)conn; 92 | return read(vde_conn->fddata,buf,len); 93 | } 94 | 95 | static ssize_t vde_macvtap_send(VDECONN *conn,const void *buf,size_t len,int flags) 96 | { 97 | struct vde_macvtap_conn *vde_conn = (struct vde_macvtap_conn *)conn; 98 | return write(vde_conn->fddata,buf,len); 99 | } 100 | 101 | static int vde_macvtap_datafd(VDECONN *conn) 102 | { 103 | struct vde_macvtap_conn *vde_conn = (struct vde_macvtap_conn *)conn; 104 | return vde_conn->fddata; 105 | } 106 | 107 | static int vde_macvtap_ctlfd(VDECONN *conn) 108 | { 109 | return -1; 110 | } 111 | 112 | static int vde_macvtap_close(VDECONN *conn) 113 | { 114 | struct vde_macvtap_conn *vde_conn = (struct vde_macvtap_conn *)conn; 115 | close(vde_conn->fddata); 116 | free(vde_conn); 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_multi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include "libvdeplug_netnode.h" 21 | 22 | struct vdeplug_module vdeplug_ops; 23 | 24 | static __attribute__ ((constructor)) void __init__(void) { 25 | vdeplug_ops = vdeplug_multi_ops; 26 | } 27 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_netnode.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVDEPLUG_NETNODE_H 2 | #define LIBVDEPLUG_NETNODE_H 3 | 4 | #include 5 | #include "libvdeplug_mod.h" 6 | 7 | extern struct vdeplug_module vdeplug_hub_ops; 8 | extern struct vdeplug_module vdeplug_multi_ops; 9 | extern struct vdeplug_module vdeplug_switch_ops; 10 | extern struct vdeplug_module vdeplug_bonding_ops; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_null.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #define _GNU_SOURCE 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "libvdeplug_mod.h" 30 | 31 | static VDECONN *vde_null_open(char *given_vde_url, char *descr,int interface_version, 32 | struct vde_open_args *open_args); 33 | static ssize_t vde_null_recv(VDECONN *conn,void *buf,size_t len,int flags); 34 | static ssize_t vde_null_send(VDECONN *conn,const void *buf,size_t len,int flags); 35 | static int vde_null_datafd(VDECONN *conn); 36 | static int vde_null_ctlfd(VDECONN *conn); 37 | static int vde_null_close(VDECONN *conn); 38 | 39 | struct vdeplug_module vdeplug_ops={ 40 | .vde_open_real=vde_null_open, 41 | .vde_recv=vde_null_recv, 42 | .vde_send=vde_null_send, 43 | .vde_datafd=vde_null_datafd, 44 | .vde_ctlfd=vde_null_ctlfd, 45 | .vde_close=vde_null_close}; 46 | 47 | struct vde_null_conn { 48 | void *handle; 49 | struct vdeplug_module *module; 50 | int fddata; 51 | }; 52 | 53 | static VDECONN *vde_null_open(char *given_vde_url, char *descr,int interface_version, 54 | struct vde_open_args *open_args) 55 | { 56 | struct vde_null_conn *newconn; 57 | int fddata = eventfd(0, EFD_CLOEXEC); 58 | if (fddata < 0) 59 | goto abort; 60 | 61 | if ((newconn=calloc(1,sizeof(struct vde_null_conn)))==NULL) { 62 | errno=ENOMEM; 63 | goto abort; 64 | } 65 | 66 | newconn->fddata=fddata; 67 | 68 | return (VDECONN *)newconn; 69 | abort: 70 | if (fddata >= 0) close(fddata); 71 | return NULL; 72 | } 73 | 74 | static ssize_t vde_null_recv(VDECONN *conn,void *buf,size_t len,int flags) 75 | { 76 | //struct vde_null_conn *vde_conn = (struct vde_null_conn *)conn; 77 | return 1; 78 | } 79 | 80 | static ssize_t vde_null_send(VDECONN *conn,const void *buf,size_t len,int flags) 81 | { 82 | //struct vde_null_conn *vde_conn = (struct vde_null_conn *)conn; 83 | return len; 84 | } 85 | 86 | static int vde_null_datafd(VDECONN *conn) 87 | { 88 | struct vde_null_conn *vde_conn = (struct vde_null_conn *)conn; 89 | return vde_conn->fddata; 90 | } 91 | 92 | static int vde_null_ctlfd(VDECONN *conn) 93 | { 94 | return -1; 95 | } 96 | 97 | static int vde_null_close(VDECONN *conn) 98 | { 99 | struct vde_null_conn *vde_conn = (struct vde_null_conn *)conn; 100 | close(vde_conn->fddata); 101 | free(vde_conn); 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_ptp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * point to point link 4 | * Copyright (C) 2013-2025 Renzo Davoli, University of Bologna 5 | * 6 | * This library is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation version 2.1 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "libvdeplug_mod.h" 37 | 38 | #define UNIX_PATH_MAX 108 39 | #define EPOLL_DATAFD 0 40 | #define EPOLL_LISTENFD 1 41 | #define ETH_HEADER_SIZE 14 42 | 43 | static VDECONN *vde_ptp_open(char *given_vde_url, char *descr,int interface_version, 44 | struct vde_open_args *open_args); 45 | static ssize_t vde_ptp_recv(VDECONN *conn,void *buf,size_t len,int flags); 46 | static ssize_t vde_ptp_send(VDECONN *conn,const void *buf,size_t len,int flags); 47 | static int vde_ptp_datafd(VDECONN *conn); 48 | static int vde_ptp_ctlfd(VDECONN *conn); 49 | static int vde_ptp_close(VDECONN *conn); 50 | 51 | struct vdeplug_module vdeplug_ops={ 52 | .vde_open_real=vde_ptp_open, 53 | .vde_recv=vde_ptp_recv, 54 | .vde_send=vde_ptp_send, 55 | .vde_datafd=vde_ptp_datafd, 56 | .vde_ctlfd=vde_ptp_ctlfd, 57 | .vde_close=vde_ptp_close}; 58 | 59 | struct vde_ptp_conn { 60 | void *handle; 61 | struct vdeplug_module *module; 62 | int datafd; 63 | int listenfd; 64 | int epollfd; 65 | char path[UNIX_PATH_MAX]; 66 | }; 67 | 68 | #define UNUSED(...) (void)(__VA_ARGS__) 69 | 70 | static int get1byteack(int fd) { 71 | unsigned char err; 72 | struct pollfd pfd[] = {{fd, POLLIN, 0}}; 73 | int ret = poll(pfd, 1, 2000); 74 | if (ret <= 0) { 75 | if (ret == 0) errno = ETIMEDOUT; 76 | return -1; 77 | } 78 | ret = recv(fd, &err, 1, 0); 79 | if (ret == 1) { 80 | if (err == 0) return 0; 81 | errno = err; 82 | } else if (ret == 0) 83 | errno = EFAULT; 84 | return -1; 85 | } 86 | 87 | static int ptpconnect(struct vde_ptp_conn *conn) { 88 | int fd; 89 | struct sockaddr_un addr = { 90 | .sun_family = AF_UNIX 91 | }; 92 | memcpy(addr.sun_path, conn->path, UNIX_PATH_MAX); 93 | if (conn->datafd >= 0 || conn->listenfd >= 0) 94 | return errno = EISCONN, -1; 95 | if ((fd = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0)) < 0) 96 | return -1; 97 | for (;;) { 98 | if ((connect(fd, (const struct sockaddr *) &addr, sizeof(addr))) >= 0) { 99 | /* ck 1 byte ack */ 100 | if (get1byteack(fd) < 0) { 101 | close(fd); 102 | return -1; 103 | } 104 | struct epoll_event ev = { 105 | .events = EPOLLIN | EPOLLHUP, 106 | .data.u32 = EPOLL_DATAFD 107 | }; 108 | if ((epoll_ctl(conn->epollfd, EPOLL_CTL_ADD, fd, &ev)) < 0) { 109 | close(fd); 110 | return -1; 111 | } 112 | conn->datafd = fd; 113 | return 0; 114 | } 115 | if (errno == ENOENT) { 116 | if ((bind(fd, (const struct sockaddr *) &addr, sizeof(addr))) >= 0) { 117 | struct epoll_event ev = { 118 | .events = EPOLLIN | EPOLLHUP, 119 | .data.u32 = EPOLL_LISTENFD 120 | }; 121 | if (listen(fd, 1) < 0) { 122 | close(fd); 123 | return -1; 124 | } 125 | if ((epoll_ctl(conn->epollfd, EPOLL_CTL_ADD, fd, &ev)) < 0) { 126 | close(fd); 127 | return -1; 128 | } 129 | conn->listenfd = fd; 130 | return 0; 131 | } 132 | if (errno == EADDRINUSE) 133 | continue; // try again! 134 | if (errno == ECONNREFUSED) { 135 | unlink(conn->path); 136 | continue; 137 | } 138 | } 139 | return -1; 140 | } 141 | return 0; 142 | } 143 | 144 | static VDECONN *vde_ptp_open(char *given_vde_url, char *descr,int interface_version, 145 | struct vde_open_args *open_args) 146 | { 147 | struct vde_ptp_conn *newconn; 148 | if ((newconn = calloc(1,sizeof(struct vde_ptp_conn))) == NULL) 149 | goto abort; 150 | newconn->datafd = -1; 151 | newconn->listenfd = -1; 152 | if ((newconn->epollfd = epoll_create1(EPOLL_CLOEXEC)) < 0) 153 | goto abort_calloc; 154 | memset(newconn->path, 0, UNIX_PATH_MAX); 155 | snprintf(newconn->path, UNIX_PATH_MAX, "%s", given_vde_url); 156 | 157 | if (ptpconnect(newconn) < 0) 158 | goto abort_calloc; 159 | 160 | return (VDECONN *)newconn; 161 | 162 | abort_calloc: 163 | free(newconn); 164 | abort: 165 | return NULL; 166 | } 167 | 168 | static ssize_t vde_ptp_recv(VDECONN *conn, void *buf, size_t len, int flags) 169 | { 170 | struct vde_ptp_conn *vde_conn = (struct vde_ptp_conn *)conn; 171 | struct epoll_event ev; 172 | int ret = epoll_wait(vde_conn->epollfd, &ev, 1, -1); 173 | if (ret == 1) { 174 | if (ev.data.u32 == EPOLL_DATAFD) { 175 | if (ev.events & EPOLLHUP) { 176 | close(vde_conn->datafd); 177 | epoll_ctl(vde_conn->epollfd, EPOLL_CTL_DEL, vde_conn->datafd, &ev); 178 | vde_conn->datafd = -1; 179 | if (vde_conn->listenfd < 0) { 180 | if (ptpconnect(vde_conn) < 0) 181 | return -1; 182 | } 183 | } 184 | if (ev.events & EPOLLIN) { 185 | return recv(vde_conn->datafd, buf, len, 0); 186 | } 187 | } 188 | if (ev.data.u32 == EPOLL_LISTENFD) { 189 | if (ev.events & EPOLLIN) { 190 | int fd = accept(vde_conn->listenfd, NULL, NULL); 191 | if (fd < 0) 192 | return -1; 193 | if (vde_conn->datafd >= 0) { 194 | unsigned char err = EISCONN; 195 | send(fd, &err, 1, 0); 196 | close(fd); // 1 char ack 197 | } else { 198 | char err = 0; 199 | send(fd, &err, 1, 0); 200 | ev.events = EPOLLIN | EPOLLHUP; 201 | ev.data.u32 = EPOLL_DATAFD; 202 | if ((epoll_ctl(vde_conn->epollfd, EPOLL_CTL_ADD, fd, &ev)) < 0) { 203 | close(fd); 204 | return -1; 205 | } 206 | vde_conn->datafd = fd; 207 | } 208 | } 209 | } 210 | } 211 | return 1; 212 | } 213 | 214 | static ssize_t vde_ptp_send(VDECONN *conn, const void *buf, size_t len, int flags) 215 | { 216 | struct vde_ptp_conn *vde_conn = (struct vde_ptp_conn *)conn; 217 | if (vde_conn->datafd >= 0 && len >= ETH_HEADER_SIZE) 218 | return send(vde_conn->datafd, buf, len, MSG_DONTWAIT); 219 | return len; // drop pckt if not connected 220 | } 221 | 222 | static int vde_ptp_datafd(VDECONN *conn) 223 | { 224 | struct vde_ptp_conn *vde_conn = (struct vde_ptp_conn *)conn; 225 | return vde_conn->epollfd; 226 | } 227 | 228 | static int vde_ptp_ctlfd(VDECONN *conn) 229 | { 230 | return -1; 231 | } 232 | 233 | static int vde_ptp_close(VDECONN *conn) 234 | { 235 | struct vde_ptp_conn *vde_conn = (struct vde_ptp_conn *)conn; 236 | if (vde_conn->listenfd >= 0) { 237 | unlink(vde_conn->path); 238 | close(vde_conn->listenfd); 239 | } 240 | if (vde_conn->datafd >= 0) 241 | close(vde_conn->datafd); 242 | close(vde_conn->epollfd); 243 | free(vde_conn); 244 | 245 | return 0; 246 | } 247 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_seqpacket.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "libvdeplug_mod.h" 35 | 36 | static VDECONN *vde_seqpacket_open(char *vde_url, char *descr, int interface_version, 37 | struct vde_open_args *open_args); 38 | static ssize_t vde_seqpacket_recv(VDECONN *conn, void *buf, size_t len, int flags); 39 | static ssize_t vde_seqpacket_send(VDECONN *conn, const void *buf, size_t len, int flags); 40 | static int vde_seqpacket_datafd(VDECONN *conn); 41 | static int vde_seqpacket_ctlfd(VDECONN *conn); 42 | static int vde_seqpacket_close(VDECONN *conn); 43 | 44 | struct vdeplug_module vdeplug_ops={ 45 | .vde_open_real=vde_seqpacket_open, 46 | .vde_recv=vde_seqpacket_recv, 47 | .vde_send=vde_seqpacket_send, 48 | .vde_datafd=vde_seqpacket_datafd, 49 | .vde_ctlfd=vde_seqpacket_ctlfd, 50 | .vde_close=vde_seqpacket_close}; 51 | 52 | struct vde_seqpacket_conn { 53 | void *handle; 54 | struct vdeplug_module *module; 55 | int fddata; 56 | }; 57 | 58 | static VDECONN *vde_seqpacket_open(char *vde_url, char *descr, int interface_version, 59 | struct vde_open_args *open_args) 60 | { 61 | long fddata=-1; 62 | struct vde_seqpacket_conn *newconn; 63 | 64 | errno = 0; 65 | fddata = strtol(vde_url, NULL, 0); 66 | 67 | if (errno != 0) 68 | return NULL; 69 | 70 | if (fddata < 0) { 71 | errno = EINVAL; 72 | return NULL; 73 | } 74 | 75 | if ((newconn = calloc(1, sizeof(struct vde_seqpacket_conn))) == NULL) { 76 | close(fddata); 77 | errno = ENOMEM; 78 | return NULL; 79 | } 80 | newconn->fddata=fddata; 81 | 82 | return (VDECONN *)newconn; 83 | } 84 | 85 | static ssize_t vde_seqpacket_recv(VDECONN *conn, void *buf, size_t len, int flags) 86 | { 87 | struct vde_seqpacket_conn *vde_conn = (struct vde_seqpacket_conn *)conn; 88 | return recv(vde_conn->fddata, buf, len, 0); 89 | } 90 | 91 | static ssize_t vde_seqpacket_send(VDECONN *conn, const void *buf, size_t len, int flags) 92 | { 93 | struct vde_seqpacket_conn *vde_conn = (struct vde_seqpacket_conn *)conn; 94 | /* never send zero length packets */ 95 | if (__builtin_expect(len > 0, 1)) 96 | return send(vde_conn->fddata, buf, len, 0); 97 | else 98 | return len; 99 | } 100 | 101 | static int vde_seqpacket_datafd(VDECONN *conn) 102 | { 103 | struct vde_seqpacket_conn *vde_conn = (struct vde_seqpacket_conn *)conn; 104 | return vde_conn->fddata; 105 | } 106 | 107 | static int vde_seqpacket_ctlfd(VDECONN *conn) 108 | { 109 | return -1; 110 | } 111 | 112 | static int vde_seqpacket_close(VDECONN *conn) 113 | { 114 | struct vde_seqpacket_conn *vde_conn = (struct vde_seqpacket_conn *)conn; 115 | close(vde_conn->fddata); 116 | free(vde_conn); 117 | 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_switch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include "libvdeplug_netnode.h" 21 | 22 | struct vdeplug_module vdeplug_ops; 23 | 24 | static __attribute__ ((constructor)) void __init__(void) { 25 | vdeplug_ops = vdeplug_switch_ops; 26 | } 27 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_tap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "libvdeplug_mod.h" 28 | #include 29 | #include 30 | #include 31 | 32 | static VDECONN *vde_tap_open(char *given_vde_url, char *descr,int interface_version, 33 | struct vde_open_args *open_args); 34 | static ssize_t vde_tap_recv(VDECONN *conn,void *buf,size_t len,int flags); 35 | static ssize_t vde_tap_send(VDECONN *conn,const void *buf,size_t len,int flags); 36 | static int vde_tap_datafd(VDECONN *conn); 37 | static int vde_tap_ctlfd(VDECONN *conn); 38 | static int vde_tap_close(VDECONN *conn); 39 | 40 | struct vdeplug_module vdeplug_ops={ 41 | .vde_open_real=vde_tap_open, 42 | .vde_recv=vde_tap_recv, 43 | .vde_send=vde_tap_send, 44 | .vde_datafd=vde_tap_datafd, 45 | .vde_ctlfd=vde_tap_ctlfd, 46 | .vde_close=vde_tap_close}; 47 | 48 | struct vde_tap_conn { 49 | void *handle; 50 | struct vdeplug_module *module; 51 | int fddata; 52 | }; 53 | 54 | static VDECONN *vde_tap_open(char *given_vde_url, char *descr,int interface_version, 55 | struct vde_open_args *open_args) 56 | { 57 | struct ifreq ifr; 58 | int fddata=-1; 59 | struct vde_tap_conn *newconn; 60 | 61 | if((fddata = open("/dev/net/tun", O_RDWR)) < 0) 62 | goto abort; 63 | memset(&ifr, 0, sizeof(ifr)); 64 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 65 | strncpy(ifr.ifr_name, given_vde_url, sizeof(ifr.ifr_name) - 1); 66 | //printf("tap dev=\"%s\", ifr.ifr_name=\"%s\"\n", ifr.ifr_name, given_vde_url); 67 | if(ioctl(fddata, TUNSETIFF, (void *) &ifr) < 0) 68 | goto abort; 69 | 70 | if ((newconn=calloc(1,sizeof(struct vde_tap_conn)))==NULL) { 71 | errno=ENOMEM; 72 | goto abort; 73 | } 74 | 75 | newconn->fddata=fddata; 76 | 77 | return (VDECONN *)newconn; 78 | 79 | abort: 80 | if (fddata >= 0) close(fddata); 81 | return NULL; 82 | } 83 | 84 | static ssize_t vde_tap_recv(VDECONN *conn,void *buf,size_t len,int flags) 85 | { 86 | struct vde_tap_conn *vde_conn = (struct vde_tap_conn *)conn; 87 | return read(vde_conn->fddata,buf,len); 88 | } 89 | 90 | static ssize_t vde_tap_send(VDECONN *conn,const void *buf,size_t len,int flags) 91 | { 92 | struct vde_tap_conn *vde_conn = (struct vde_tap_conn *)conn; 93 | return write(vde_conn->fddata,buf,len); 94 | } 95 | 96 | static int vde_tap_datafd(VDECONN *conn) 97 | { 98 | struct vde_tap_conn *vde_conn = (struct vde_tap_conn *)conn; 99 | return vde_conn->fddata; 100 | } 101 | 102 | static int vde_tap_ctlfd(VDECONN *conn) 103 | { 104 | return -1; 105 | } 106 | 107 | static int vde_tap_close(VDECONN *conn) 108 | { 109 | struct vde_tap_conn *vde_conn = (struct vde_tap_conn *)conn; 110 | close(vde_conn->fddata); 111 | free(vde_conn); 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_udp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2016 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "libvdeplug_mod.h" 35 | 36 | static VDECONN *vde_udp_open(char *vde_url, char *descr,int interface_version, 37 | struct vde_open_args *open_args); 38 | static ssize_t vde_udp_recv(VDECONN *conn,void *buf,size_t len,int flags); 39 | static ssize_t vde_udp_send(VDECONN *conn,const void *buf,size_t len,int flags); 40 | static int vde_udp_datafd(VDECONN *conn); 41 | static int vde_udp_ctlfd(VDECONN *conn); 42 | static int vde_udp_close(VDECONN *conn); 43 | 44 | struct vdeplug_module vdeplug_ops={ 45 | .vde_open_real=vde_udp_open, 46 | .vde_recv=vde_udp_recv, 47 | .vde_send=vde_udp_send, 48 | .vde_datafd=vde_udp_datafd, 49 | .vde_ctlfd=vde_udp_ctlfd, 50 | .vde_close=vde_udp_close}; 51 | 52 | struct vde_udp_conn { 53 | void *handle; 54 | struct vdeplug_module *module; 55 | int fddata; 56 | struct sockaddr *outsock; 57 | size_t outlen; 58 | }; 59 | 60 | static VDECONN *vde_udp_open(char *vde_url, char *descr,int interface_version, 61 | struct vde_open_args *open_args) 62 | { 63 | int fddata=-1; 64 | struct addrinfo hints; 65 | struct addrinfo *srcresult=NULL; 66 | struct addrinfo *dstresult=NULL; 67 | struct addrinfo *rp; 68 | int s; 69 | char *dst; 70 | char *src=vde_url; 71 | char *srcport; 72 | char *dstport; 73 | struct vde_udp_conn *newconn; 74 | 75 | dst=strstr(vde_url,"->"); 76 | //printf("%s\n",vde_url); 77 | 78 | if (dst == NULL) 79 | return NULL; 80 | 81 | memset(&hints,0,sizeof(hints)); 82 | hints.ai_socktype=SOCK_DGRAM; 83 | *dst=0; 84 | dst+=2; 85 | dstport=rindex(dst,':'); 86 | if (dstport==NULL) { 87 | errno=EINVAL; 88 | goto abort; 89 | } 90 | *dstport=0; 91 | dstport++; 92 | srcport=rindex(src,':'); 93 | if (srcport==NULL) { 94 | srcport=src; 95 | src=NULL; 96 | } else { 97 | if (srcport==src) 98 | src=NULL; 99 | *srcport=0; 100 | srcport++; 101 | } 102 | 103 | if ((s = getaddrinfo(dst, dstport, &hints, &dstresult)) != 0) { 104 | //fprintf(stderr,"%s: %s\n",dst,gai_strerror(s)); 105 | errno=ECONNABORTED; 106 | goto abort; 107 | } 108 | 109 | hints.ai_flags = AI_PASSIVE; 110 | hints.ai_family = dstresult->ai_family; 111 | 112 | s = getaddrinfo(src, srcport, &hints, &srcresult); 113 | 114 | if (s != 0) { 115 | //fprintf(stderr,"%s: %s\n",src,gai_strerror(s)); 116 | errno=ECONNABORTED; 117 | goto abort; 118 | } 119 | 120 | for (rp = srcresult; rp != NULL; rp = rp->ai_next) { 121 | fddata = socket(rp->ai_family, rp->ai_socktype | SOCK_CLOEXEC, rp->ai_protocol); 122 | if (fddata == -1) 123 | continue; 124 | 125 | if (bind(fddata, rp->ai_addr, rp->ai_addrlen) == 0) 126 | break; /* Success */ 127 | 128 | close(fddata); 129 | } 130 | 131 | if (rp == NULL) { 132 | errno=ECONNABORTED; 133 | goto abort; 134 | } 135 | 136 | freeaddrinfo(srcresult); 137 | 138 | //fprintf(stderr,"UDP!%s:%s -> %s:%s \n",src,srcport,dst,dstport); 139 | if ((newconn=calloc(1,sizeof(struct vde_udp_conn)))==NULL) 140 | { 141 | errno=ENOMEM; 142 | goto abort; 143 | } 144 | 145 | newconn->fddata=fddata; 146 | newconn->outsock = malloc(dstresult->ai_addrlen); 147 | newconn->outlen = dstresult->ai_addrlen; 148 | memcpy(newconn->outsock, dstresult->ai_addr, dstresult->ai_addrlen); 149 | 150 | freeaddrinfo(dstresult); 151 | 152 | return (VDECONN *)newconn; 153 | 154 | abort: 155 | if (fddata >= 0) close(fddata); 156 | if (dstresult) freeaddrinfo(dstresult); 157 | if (srcresult) freeaddrinfo(srcresult); 158 | return NULL; 159 | } 160 | 161 | static ssize_t vde_udp_recv(VDECONN *conn,void *buf,size_t len,int flags) 162 | { 163 | struct vde_udp_conn *vde_conn = (struct vde_udp_conn *)conn; 164 | #ifdef CONNECTED_P2P 165 | ssize_t retval; 166 | if (__builtin_expect(((retval=recv(vde_conn->fddata,buf,len,0)) > 0), 1)) 167 | return retval; 168 | else { 169 | if (retval == 0 && vde_conn->outsock != NULL) { 170 | static struct sockaddr unspec={AF_UNSPEC}; 171 | connect(vde_conn->fddata,&unspec,sizeof(unspec)); 172 | } 173 | return retval; 174 | } 175 | #else 176 | return recv(vde_conn->fddata,buf,len,0); 177 | #endif 178 | } 179 | 180 | static ssize_t vde_udp_send(VDECONN *conn,const void *buf,size_t len,int flags) 181 | { 182 | struct vde_udp_conn *vde_conn = (struct vde_udp_conn *)conn; 183 | #ifdef CONNECTED_P2P 184 | ssize_t retval; 185 | if (__builtin_expect(((retval=send(vde_conn->fddata,buf,len,0)) >= 0),1)) 186 | return retval; 187 | else { 188 | if (__builtin_expect(errno == ENOTCONN || errno == EDESTADDRREQ,0)) { 189 | if (__builtin_expect(vde_conn->outsock != NULL,1)) { 190 | connect(vde_conn->fddata, vde_conn->outsock,vde_conn->outlen); 191 | return send(vde_conn->fddata,buf,len,0); 192 | } else 193 | return retval; 194 | } else 195 | return retval; 196 | } 197 | #else 198 | return sendto(vde_conn->fddata,buf,len,0, vde_conn->outsock,vde_conn->outlen); 199 | #endif 200 | } 201 | 202 | static int vde_udp_datafd(VDECONN *conn) 203 | { 204 | struct vde_udp_conn *vde_conn = (struct vde_udp_conn *)conn; 205 | return vde_conn->fddata; 206 | } 207 | 208 | static int vde_udp_ctlfd(VDECONN *conn) 209 | { 210 | return -1; 211 | } 212 | 213 | static int vde_udp_close(VDECONN *conn) 214 | { 215 | struct vde_udp_conn *vde_conn = (struct vde_udp_conn *)conn; 216 | if (vde_conn->outsock != NULL) 217 | free(vde_conn->outsock); 218 | close(vde_conn->fddata); 219 | free(vde_conn); 220 | 221 | return 0; 222 | } 223 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_vde.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013-2017 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "libvdeplug_mod.h" 36 | 37 | static VDECONN *vde_vde_open(char *given_vde_url, char *descr, int interface_version, 38 | struct vde_open_args *open_args); 39 | static ssize_t vde_vde_recv(VDECONN *conn, void *buf, size_t len, int flags); 40 | static ssize_t vde_vde_send(VDECONN *conn, const void *buf, size_t len, int flags); 41 | static int vde_vde_datafd(VDECONN *conn); 42 | static int vde_vde_ctlfd(VDECONN *conn); 43 | static int vde_vde_close(VDECONN *conn); 44 | 45 | struct vdeplug_module vdeplug_ops={ 46 | .vde_open_real=vde_vde_open, 47 | .vde_recv=vde_vde_recv, 48 | .vde_send=vde_vde_send, 49 | .vde_datafd=vde_vde_datafd, 50 | .vde_ctlfd=vde_vde_ctlfd, 51 | .vde_close=vde_vde_close}; 52 | 53 | struct vde_vde_conn { 54 | void *hadle; 55 | struct vdeplug_module *module; 56 | int fdctl; 57 | int fddata; 58 | }; 59 | 60 | /* Fallback names for the control socket, NULL-terminated array of absolute 61 | * filenames. */ 62 | static const char *fallback_vde_url[] = { 63 | "/var/run/vde.ctl", 64 | "/tmp/vde.ctl", 65 | NULL, 66 | }; 67 | 68 | /* Fallback directories for the data socket, NULL-terminated array of absolute 69 | * directory names, with no trailing /. */ 70 | static const char *fallback_dirname[] = { 71 | "/var/run", 72 | "/var/tmp", 73 | "/tmp", 74 | NULL, 75 | }; 76 | 77 | #define SWITCH_MAGIC 0xfeedface 78 | enum request_type { REQ_NEW_CONTROL, REQ_NEW_PORT0 }; 79 | 80 | struct request_v3 { 81 | uint32_t magic; 82 | uint32_t version; 83 | enum request_type type; 84 | struct sockaddr_un sock; 85 | char description[MAXDESCR]; 86 | } __attribute__((packed)); 87 | 88 | /* return value: -1=error; 0=portgroup socket okay; 1=connected to generic "ctl" port */ 89 | static int try2connect(int fdctl, const char *url, char *portgroup, int port, struct sockaddr_un *ctlsock) { 90 | int res = -1; 91 | 92 | memset(ctlsock, 0, sizeof(*ctlsock)); 93 | ctlsock->sun_family = AF_UNIX; 94 | if (portgroup) { 95 | snprintf(ctlsock->sun_path, sizeof(ctlsock->sun_path), "%s/%s", url, portgroup); 96 | res = connect(fdctl, (struct sockaddr *) ctlsock, sizeof(*ctlsock)); 97 | } 98 | if (res < 0 || port != 0) { 99 | snprintf(ctlsock->sun_path, sizeof(ctlsock->sun_path), "%s/ctl", url); 100 | res = connect(fdctl, (struct sockaddr *) ctlsock, sizeof(*ctlsock)); 101 | if (res == 0) res = 1; 102 | } 103 | return res; 104 | } 105 | 106 | static VDECONN *vde_vde_open(char *given_vde_url, char *descr,int interface_version, 107 | struct vde_open_args *open_args) 108 | { 109 | struct request_v3 req; 110 | int port=0; 111 | char *portgroup=NULL; 112 | char str_lenofint = snprintf(NULL, 0, "%d ", INT_MIN); // # of char to store a int 113 | char numeric_portgroup[str_lenofint]; 114 | char *group=NULL; 115 | char *modestr=NULL; 116 | mode_t mode=0700; 117 | char real_vde_url[PATH_MAX]; 118 | int fdctl=-1; 119 | int fddata=-1; 120 | struct sockaddr_un sockun; 121 | struct sockaddr_un datasock; 122 | const char *vde_url=NULL; 123 | int res; 124 | int pid=getpid(); 125 | int sockno=0; 126 | struct vde_vde_conn *newconn; 127 | struct vdeparms parms[] = {{"", &portgroup}, {"port", &portgroup}, {"portgroup", &portgroup}, 128 | {"group", &group}, {"mode", &modestr}, {NULL, NULL}}; 129 | 130 | if (open_args != NULL) { 131 | if (interface_version == 1) { 132 | port=open_args->port; 133 | group=open_args->group; 134 | mode=open_args->mode; 135 | } else { 136 | errno=EINVAL; 137 | goto abort; 138 | } 139 | } 140 | 141 | if (vde_parsepathparms(given_vde_url, parms) < 0) { 142 | errno=EINVAL; 143 | goto abort; 144 | } 145 | 146 | if (modestr) 147 | mode = strtol(modestr, NULL, 8); 148 | 149 | /* Canonicalize the sockname: we need to send an absolute pathname to the 150 | * switch (we don't know its cwd) for the data socket. Appending 151 | * given_sockname to getcwd() would be enough, but we could end up with a 152 | * name longer than PATH_MAX that couldn't be used as sun_path. */ 153 | if (*given_vde_url && realpath(given_vde_url, real_vde_url) == NULL) 154 | goto abort; 155 | vde_url=real_vde_url; 156 | 157 | /* if port is given as a open_arg, convert it to portgroup */ 158 | if ((portgroup == NULL || *portgroup == 0) && port != 0) { 159 | snprintf(numeric_portgroup, str_lenofint, "%d", port < 0 ? 0 : port); 160 | portgroup = numeric_portgroup; 161 | } else if (portgroup != NULL && isdigit(*portgroup)) { 162 | /* else if portgroup is a number, convert it to port (and override port) */ 163 | char *endptr; 164 | int portgroup2port = strtol(portgroup, &endptr, 10); 165 | if (*endptr == 0) { 166 | port = portgroup2port; 167 | if (port == 0) port = -1; 168 | } 169 | } 170 | 171 | /* connection to a vde_switch */ 172 | if((fdctl = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) 173 | goto abort; 174 | if((fddata = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) 175 | goto abort; 176 | 177 | /* If we're given a vde_url, just try it (remember: vde_url is the 178 | * canonicalized version of given_vde_url - though we don't strictly need 179 | * the canonicalized version here). vde_url should be the name of a 180 | * *directory* which contains the control socket, named ctl. Older 181 | * versions of VDE used a socket instead of a directory (so an additional 182 | * attempt with %s instead of %s/ctl could be made), but they should 183 | * really not be used anymore. */ 184 | if (*given_vde_url) 185 | res = try2connect(fdctl, vde_url, portgroup, port, &sockun); 186 | /* Else try all the fallback vde_url, one by one */ 187 | else 188 | { 189 | int i; 190 | for (i = 0, res = -1; fallback_vde_url[i] && (res < 0); i++) 191 | { 192 | vde_url = fallback_vde_url[i]; 193 | res = try2connect(fdctl, vde_url, portgroup, port, &sockun); 194 | } 195 | } 196 | 197 | if (res < 0) 198 | goto abort; 199 | 200 | req.magic=SWITCH_MAGIC; 201 | req.version=3; 202 | req.type = REQ_NEW_CONTROL; 203 | /* bw compatibility, port embedded on type if connected to ctl */ 204 | if (res > 0 && port != 0) { 205 | if (port < 0) 206 | req.type = REQ_NEW_PORT0; 207 | else 208 | req.type=req.type+(port << 8); 209 | } 210 | strncpy(req.description, descr, MAXDESCR); 211 | 212 | datasock.sun_family = AF_UNIX; 213 | memset(datasock.sun_path, 0, sizeof(datasock.sun_path)); 214 | do 215 | { 216 | /* Here vde_url is the last successful one in the previous step. */ 217 | #pragma GCC diagnostic push 218 | /* disable format-truncation: it is the meaning of using snprintf! */ 219 | #pragma GCC diagnostic ignored "-Wformat-truncation" 220 | snprintf(datasock.sun_path, sizeof(datasock.sun_path), 221 | "%s/.%05d-%05d", vde_url, pid, sockno++); 222 | #pragma GCC diagnostic pop 223 | res=bind(fddata, (struct sockaddr *) &datasock, sizeof (datasock)); 224 | } 225 | while (res < 0 && errno == EADDRINUSE); 226 | 227 | /* It didn't work. So we cycle on the fallback directories until we find a 228 | * suitable one (or the list ends). */ 229 | if (res < 0) 230 | { 231 | int i; 232 | for (i = 0, res = -1, sockno = 0; fallback_dirname[i] && (res != 0); i++) 233 | { 234 | memset(datasock.sun_path, 0, sizeof(datasock.sun_path)); 235 | do 236 | { 237 | sprintf(datasock.sun_path, "%s/vde.%05d-%05d", fallback_dirname[i], pid, sockno++); 238 | res = bind(fddata, (struct sockaddr *) &datasock, sizeof (datasock)); 239 | } 240 | while (res < 0 && errno == EADDRINUSE); 241 | } 242 | } 243 | 244 | /* Nothing worked, so cleanup and return with an error. */ 245 | if (res < 0) 246 | goto abort; 247 | 248 | if (group) { 249 | struct group *gs; 250 | gid_t gid; 251 | if ((gs=getgrnam(group)) == NULL) 252 | gid=atoi(group); 253 | else 254 | gid=gs->gr_gid; 255 | if (chown(datasock.sun_path, -1, gid) < 0) 256 | goto abort_deletesock; 257 | } else { 258 | /* when group is not defined, set permission for the reverse channel */ 259 | struct stat ctlstat; 260 | /* if no permission gets "voluntarily" granted to the socket */ 261 | if ((mode & 077) == 0) { 262 | if (stat(sockun.sun_path, &ctlstat) == 0) { 263 | /* if the switch is owned by root or by the same user it should 264 | work 0700 */ 265 | if (ctlstat.st_uid != 0 && ctlstat.st_uid != geteuid()) { 266 | /* try to change the group ownership to the same of the switch */ 267 | /* this call succeeds if the vde user and the owner of the switch 268 | belong to the group */ 269 | if (chown(datasock.sun_path, -1, ctlstat.st_gid) == 0) 270 | mode |= 070; 271 | else 272 | mode |= 077; 273 | } 274 | } 275 | } 276 | } 277 | chmod(datasock.sun_path, mode); 278 | req.sock = datasock; 279 | 280 | if (send(fdctl, &req, sizeof(req) - MAXDESCR + strlen(req.description), 0) < 0) 281 | goto abort_deletesock; 282 | 283 | if (recv(fdctl, &datasock, sizeof(struct sockaddr_un), 0) <= 0) 284 | goto abort_deletesock; 285 | 286 | if (connect(fddata, (struct sockaddr *)&datasock, sizeof(struct sockaddr_un)) < 0) 287 | goto abort_deletesock; 288 | 289 | chmod(datasock.sun_path, mode); 290 | 291 | if ((newconn=calloc(1, sizeof(struct vde_vde_conn)))==NULL) 292 | { 293 | errno=ENOMEM; 294 | goto abort_deletesock; 295 | } 296 | 297 | newconn->fdctl=fdctl; 298 | newconn->fddata=fddata; 299 | unlink(req.sock.sun_path); 300 | 301 | return (VDECONN *)newconn; 302 | 303 | abort_deletesock: 304 | unlink(req.sock.sun_path); 305 | abort: 306 | if (fdctl >= 0) close(fdctl); 307 | if (fddata >= 0) close(fddata); 308 | return NULL; 309 | } 310 | 311 | static ssize_t vde_vde_recv(VDECONN *conn, void *buf, size_t len, int flags) 312 | { 313 | struct vde_vde_conn *vde_conn = (struct vde_vde_conn *)conn; 314 | return recv(vde_conn->fddata, buf, len, 0); 315 | } 316 | 317 | static ssize_t vde_vde_send(VDECONN *conn, const void *buf, size_t len, int flags) 318 | { 319 | struct vde_vde_conn *vde_conn = (struct vde_vde_conn *)conn; 320 | return send(vde_conn->fddata, buf, len, 0); 321 | } 322 | 323 | static int vde_vde_datafd(VDECONN *conn) 324 | { 325 | struct vde_vde_conn *vde_conn = (struct vde_vde_conn *)conn; 326 | return vde_conn->fddata; 327 | } 328 | 329 | static int vde_vde_ctlfd(VDECONN *conn) 330 | { 331 | struct vde_vde_conn *vde_conn = (struct vde_vde_conn *)conn; 332 | return vde_conn->fdctl; 333 | } 334 | 335 | static int vde_vde_close(VDECONN *conn) 336 | { 337 | struct vde_vde_conn *vde_conn = (struct vde_vde_conn *)conn; 338 | close(vde_conn->fddata); 339 | close(vde_conn->fdctl); 340 | free(vde_conn); 341 | 342 | return 0; 343 | } 344 | -------------------------------------------------------------------------------- /libvdeplug4/libvdeplug_vxlan.c: -------------------------------------------------------------------------------- 1 | /* 2 | * VDE - libvdeplug_vx modules 3 | * Copyright (C) 2014-2016 Renzo Davoli VirtualSquare 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "libvdeplug_mod.h" 35 | 36 | #define DEFADDRV4 "239.0.0.1" 37 | #define DEFADDRV6 "ff05:56de::1" 38 | #define STDPORTSTR "4789" 39 | #define STDTTLSTR "1" 40 | #define STDVNISTR "1" 41 | #define STDHASHSIZE 1024 42 | #define STDEXPIRETIME 128 43 | 44 | #define ETH_ALEN 6 45 | #define ETH_HEADER_SIZE 14 46 | #define IS_BROADCAST(addr) ((addr[0] & 1) == 1) 47 | 48 | #define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2])) 49 | #define hton24(p, v) { \ 50 | p[0] = (((v) >> 16) & 0xFF); \ 51 | p[1] = (((v) >> 8) & 0xFF); \ 52 | p[2] = ((v) & 0xFF); \ 53 | } 54 | 55 | struct eth_hdr { 56 | unsigned char dest[ETH_ALEN]; 57 | unsigned char src[ETH_ALEN]; 58 | unsigned char proto[2]; 59 | }; 60 | 61 | struct vxlan_hdr { 62 | unsigned char flags; 63 | unsigned char priv1[3]; 64 | unsigned char id[3]; 65 | unsigned char priv2[1]; 66 | }; 67 | 68 | static VDECONN *vde_vxlan_open(char *given_vde_url, char *descr,int interface_version, 69 | struct vde_open_args *open_args); 70 | static ssize_t vde_vxlan_recv(VDECONN *conn,void *buf,size_t len,int flags); 71 | static ssize_t vde_vxlan_send(VDECONN *conn,const void *buf,size_t len,int flags); 72 | static int vde_vxlan_datafd(VDECONN *conn); 73 | static int vde_vxlan_ctlfd(VDECONN *conn); 74 | static int vde_vxlan_close(VDECONN *conn); 75 | 76 | union sockaddr46 { 77 | struct sockaddr vx; 78 | struct sockaddr_in v4; 79 | struct sockaddr_in6 v6; 80 | }; 81 | 82 | struct vde_vxlan_conn { 83 | void *handle; 84 | struct vdeplug_module *module; 85 | struct vde_hashtable *table; 86 | int vni; 87 | union sockaddr46 multiaddr; 88 | in_port_t multiport; 89 | int multifd; 90 | int expiretime; 91 | }; 92 | 93 | struct vdeplug_module vdeplug_ops={ 94 | .vde_open_real=vde_vxlan_open, 95 | .vde_recv=vde_vxlan_recv, 96 | .vde_send=vde_vxlan_send, 97 | .vde_datafd=vde_vxlan_datafd, 98 | .vde_ctlfd=vde_vxlan_ctlfd, 99 | .vde_close=vde_vxlan_close 100 | }; 101 | 102 | static inline socklen_t fam2socklen(void *sockaddr) 103 | { 104 | struct sockaddr *s=sockaddr; 105 | switch (s->sa_family) { 106 | case AF_INET: return sizeof(struct sockaddr_in); 107 | case AF_INET6: return sizeof(struct sockaddr_in6); 108 | default: return 0; 109 | } 110 | } 111 | 112 | static inline void setport(void *sockaddr, in_port_t port) 113 | { 114 | struct sockaddr *s=sockaddr; 115 | switch (s->sa_family) { 116 | case AF_INET: ((struct sockaddr_in *) s)->sin_port = port; 117 | return; 118 | case AF_INET6: ((struct sockaddr_in6 *) s)->sin6_port = port; 119 | return; 120 | } 121 | } 122 | 123 | static VDECONN *vde_vxlan_open(char *vde_url, char *descr,int interface_version, 124 | struct vde_open_args *open_args) 125 | { 126 | struct vde_vxlan_conn *newconn; 127 | struct addrinfo hints; 128 | struct addrinfo *result,*rp; 129 | int s; 130 | unsigned int hashsize = STDHASHSIZE; 131 | char *portstr = STDPORTSTR; 132 | char *vnistr = STDVNISTR; 133 | char *ttlstr = STDTTLSTR; 134 | char *rcvbufstr = NULL; 135 | char *v6str = NULL; 136 | char *v4str = NULL; 137 | char *hashsizestr = NULL; 138 | char *expiretimestr = NULL; 139 | char *ifstr = NULL; 140 | struct vdeparms parms[] = { 141 | {"port",&portstr}, 142 | {"vni",&vnistr}, 143 | {"ttl",&ttlstr}, 144 | {"rcvbuf",&rcvbufstr}, 145 | {"v6",&v6str}, 146 | {"v4",&v4str}, 147 | {"hashsize",&hashsizestr}, 148 | {"expiretime",&expiretimestr}, 149 | {"if",&ifstr}, 150 | {NULL, NULL}}; 151 | struct sockaddr *multiaddr=NULL; 152 | int multifd=-1; 153 | int ttl; 154 | in_port_t multiport; 155 | unsigned int ifindex = 0; 156 | 157 | memset(&hints, 0, sizeof(struct addrinfo)); 158 | /* Allow IPv4 or IPv6 if either none or both options v4/v6 were selected*/ 159 | switch (((!!v6str) << 1) | (!!v4str)) { 160 | case 0: hints.ai_family = AF_UNSPEC; break; 161 | case 1: hints.ai_family = AF_INET; break; 162 | case 2: hints.ai_family = AF_INET6; break; 163 | case 3: hints.ai_family = AF_UNSPEC; break; 164 | } 165 | hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ 166 | hints.ai_protocol = 0; /* Any protocol */ 167 | if (vde_parseparms(vde_url, parms) != 0) 168 | return NULL; 169 | ttl = atoi(ttlstr); 170 | 171 | if (*vde_url == 0) 172 | vde_url = v6str != NULL ? DEFADDRV6 : DEFADDRV4; 173 | if (ifstr != NULL) 174 | ifindex = if_nametoindex(ifstr); 175 | 176 | s = getaddrinfo(vde_url, portstr, &hints, &result); 177 | if (s < 0) { 178 | fprintf(stderr, "vxlan getaddrinfo: %s\n", gai_strerror(s)); 179 | errno=ENOENT; 180 | return NULL; 181 | } 182 | 183 | for (rp = result; rp != NULL && multifd < 0; rp = rp->ai_next) { 184 | switch (rp->ai_family) { 185 | case AF_INET6: { 186 | struct sockaddr_in6 *addr=(struct sockaddr_in6 *)(rp->ai_addr); 187 | struct ipv6_mreq mc_req; 188 | multiaddr = (struct sockaddr *) addr; 189 | struct sockaddr_in6 bindaddr; 190 | int loop = 0; 191 | 192 | if ((multifd=socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP)) < 0) 193 | goto error; 194 | if (rcvbufstr) { 195 | unsigned int rcvbuf = strtoullm(rcvbufstr); 196 | if ((setsockopt(multifd, SOL_SOCKET, SO_RCVBUF, 197 | &rcvbuf, sizeof(rcvbuf))) < 0) 198 | goto error; 199 | } 200 | if ((setsockopt(multifd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 201 | &ttl, sizeof(ttl))) < 0) 202 | goto error; 203 | if ((setsockopt(multifd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 204 | &loop, sizeof(loop))) < 0) 205 | goto error; 206 | 207 | /* bind to in6addr_any to receive both unicast and multicast */ 208 | memset(&bindaddr, 0, sizeof(bindaddr)); 209 | bindaddr.sin6_family = AF_INET6; 210 | memcpy(&bindaddr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); 211 | bindaddr.sin6_port = multiport = addr->sin6_port; 212 | if ((bind(multifd, (struct sockaddr *) &bindaddr, 213 | sizeof(bindaddr))) < 0) { 214 | close(multifd); 215 | multifd=-1; 216 | continue; 217 | } 218 | 219 | memcpy(&mc_req.ipv6mr_multiaddr, &addr->sin6_addr, 220 | sizeof(addr->sin6_addr)); 221 | mc_req.ipv6mr_interface = ifindex; 222 | if ((setsockopt(multifd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, 223 | &mc_req, sizeof(mc_req))) < 0) 224 | goto error; 225 | if (ifindex > 0) { 226 | if ((setsockopt(multifd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, 227 | sizeof(ifindex))) < 0) 228 | goto error; 229 | } 230 | break; 231 | } 232 | case AF_INET: { 233 | struct sockaddr_in *addr=(struct sockaddr_in *)(rp->ai_addr); 234 | struct ip_mreqn mc_req; 235 | multiaddr = (struct sockaddr *) addr; 236 | struct sockaddr_in bindaddr; 237 | int loop = 0; 238 | 239 | if ((multifd=socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP)) < 0) 240 | goto error; 241 | if (rcvbufstr) { 242 | unsigned int rcvbuf = strtoullm(rcvbufstr); 243 | if ((setsockopt(multifd, SOL_SOCKET, SO_RCVBUF, 244 | &rcvbuf, sizeof(rcvbuf))) < 0) 245 | goto error; 246 | } 247 | if ((setsockopt(multifd, IPPROTO_IP, IP_MULTICAST_TTL, 248 | &ttl, sizeof(ttl))) < 0) 249 | goto error; 250 | if ((setsockopt(multifd, IPPROTO_IP, IP_MULTICAST_LOOP, 251 | &loop, sizeof(loop))) < 0) 252 | goto error; 253 | 254 | memset(&bindaddr, 0, sizeof(bindaddr)); 255 | bindaddr.sin_family = AF_INET; 256 | bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); 257 | bindaddr.sin_port = multiport = addr->sin_port; 258 | if ((bind(multifd, (struct sockaddr *) &bindaddr, 259 | sizeof(bindaddr))) < 0) { 260 | close(multifd); 261 | multifd=-1; 262 | continue; 263 | } 264 | 265 | mc_req.imr_multiaddr.s_addr = addr->sin_addr.s_addr; 266 | mc_req.imr_address.s_addr = htonl(INADDR_ANY); 267 | mc_req.imr_ifindex = ifindex; 268 | if ((setsockopt(multifd, IPPROTO_IP, IP_ADD_MEMBERSHIP, 269 | &mc_req, sizeof(mc_req))) < 0) 270 | goto error; 271 | 272 | if (ifindex > 0) { 273 | mc_req.imr_multiaddr.s_addr = htonl(INADDR_ANY); 274 | mc_req.imr_address.s_addr = htonl(INADDR_ANY); 275 | mc_req.imr_ifindex = ifindex; 276 | if ((setsockopt(multifd, IPPROTO_IP, IP_MULTICAST_IF, &mc_req, 277 | sizeof(mc_req))) < 0) 278 | goto error; 279 | } 280 | break; 281 | } 282 | } 283 | } 284 | 285 | if (multifd < 0) { 286 | errno = ENETUNREACH; 287 | goto error; 288 | } 289 | 290 | if ((newconn=calloc(1,sizeof(struct vde_vxlan_conn)))==NULL) 291 | { 292 | errno = ENOMEM; 293 | goto error; 294 | } 295 | 296 | if (hashsizestr != NULL) 297 | hashsize = atoi(hashsizestr); 298 | switch (multiaddr->sa_family) { 299 | case AF_INET6: 300 | newconn->table = vde_hash_init(struct sockaddr_in6 , hashsize, 0); 301 | break; 302 | case AF_INET: 303 | newconn->table = vde_hash_init(struct sockaddr_in , hashsize, 0); 304 | break; 305 | default: 306 | newconn->table = NULL; 307 | break; 308 | } 309 | newconn->vni=atoi(vnistr); 310 | if (expiretimestr != NULL) { 311 | newconn->expiretime = atoi(expiretimestr); 312 | if (newconn->expiretime <= 0) 313 | newconn->expiretime = STDEXPIRETIME; 314 | } else 315 | newconn->expiretime = STDEXPIRETIME; 316 | memcpy(&(newconn->multiaddr.vx), multiaddr, fam2socklen(multiaddr)); 317 | newconn->multiport = multiport; 318 | newconn->multifd = multifd; 319 | freeaddrinfo(result); 320 | return (VDECONN *) newconn; 321 | 322 | error: 323 | freeaddrinfo(result); 324 | if (multifd >= 0) close(multifd); 325 | if (newconn != NULL) free(newconn); 326 | return NULL; 327 | } 328 | 329 | static ssize_t vde_vxlan_recv(VDECONN *conn,void *buf,size_t len,int flags) { 330 | struct vde_vxlan_conn *vde_conn = (struct vde_vxlan_conn *)conn; 331 | struct vxlan_hdr vhdr; 332 | struct iovec iov[]={{&vhdr, sizeof(vhdr)},{buf, len}}; 333 | struct msghdr msg; 334 | struct sockaddr_in6 sender; 335 | ssize_t retval; 336 | msg.msg_name=&sender; 337 | msg.msg_namelen = fam2socklen(msg.msg_name); 338 | msg.msg_iov=iov; 339 | msg.msg_iovlen=2; 340 | msg.msg_control=NULL; 341 | msg.msg_controllen=0; 342 | msg.msg_flags=0; 343 | retval=recvmsg(vde_conn->multifd, &msg, 0)-sizeof(struct vxlan_hdr); 344 | if (__builtin_expect((retval > ETH_HEADER_SIZE), 1)) { 345 | struct eth_hdr *ehdr=(struct eth_hdr *) buf; 346 | if (vhdr.flags != (1 << 3) || ntoh24(vhdr.id) != vde_conn->vni) 347 | goto error; 348 | /* VXLAN always sends packets to the multicast port */ 349 | setport(msg.msg_name, vde_conn->multiport); 350 | vde_find_in_hash_update(vde_conn->table, ehdr->src, 1, msg.msg_name, time(NULL)); 351 | return retval; 352 | } 353 | error: 354 | errno = EAGAIN; 355 | *((unsigned char *)buf)=0; 356 | return 1; 357 | } 358 | 359 | static ssize_t vde_vxlan_send(VDECONN *conn,const void *buf, size_t len,int flags) { 360 | struct vde_vxlan_conn *vde_conn = (struct vde_vxlan_conn *)conn; 361 | struct vxlan_hdr vhdr; 362 | struct iovec iov[]={{&vhdr, sizeof(vhdr)},{(char *)buf, len}}; 363 | struct sockaddr *destaddr; 364 | static struct msghdr msg; 365 | ssize_t retval; 366 | msg.msg_iov=iov; 367 | msg.msg_iovlen=2; 368 | struct eth_hdr *ehdr=(struct eth_hdr *) buf; 369 | if (len < ETH_HEADER_SIZE) 370 | return len; // discard packets shorter than an ethernet header 371 | if (IS_BROADCAST(ehdr->dest) || 372 | (destaddr = vde_find_in_hash(vde_conn->table, ehdr->dest, 1, time(NULL)- vde_conn->expiretime)) == NULL) 373 | /* MULTICAST */ 374 | msg.msg_name = &(vde_conn->multiaddr.vx); 375 | else 376 | /* UNICAST */ 377 | msg.msg_name = destaddr; 378 | msg.msg_namelen = fam2socklen(msg.msg_name); 379 | memset(&vhdr, 0, sizeof(vhdr)); 380 | vhdr.flags = (1 << 3); 381 | 382 | hton24(vhdr.id, vde_conn->vni); 383 | 384 | if ((retval=sendmsg(vde_conn->multifd, &msg, 0)) < 0) 385 | return -1; 386 | retval -= sizeof(struct vxlan_hdr); 387 | if (retval < 0) 388 | retval = 0; 389 | return retval; 390 | } 391 | 392 | static int vde_vxlan_datafd(VDECONN *conn) { 393 | struct vde_vxlan_conn *vde_conn = (struct vde_vxlan_conn *)conn; 394 | return vde_conn->multifd; 395 | } 396 | 397 | static int vde_vxlan_ctlfd(VDECONN *conn) { 398 | return -1; 399 | } 400 | 401 | static int vde_vxlan_close(VDECONN *conn) { 402 | struct vde_vxlan_conn *vde_conn = (struct vde_vxlan_conn *)conn; 403 | close(vde_conn->multifd); 404 | vde_hash_fini(vde_conn->table); 405 | free(vde_conn); 406 | return 0; 407 | } 408 | -------------------------------------------------------------------------------- /libvdeplug4/libvdestream.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * Copyright (C) 2013 Renzo Davoli, University of Bologna 4 | * 5 | * This library is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation version 2.1 of the License, or (at 8 | * your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define MAXPACKET (VDE_ETHBUFSIZE + 2) 31 | #ifndef MIN 32 | #define MIN(X,Y) (((X)<(Y))?(X):(Y)) 33 | #endif 34 | 35 | struct vdestream { 36 | void *opaque; 37 | int fdout; 38 | ssize_t (*frecv)(void *opaque, void *buf, size_t count); 39 | void (*ferr)(void *opaque, int type, char *format, ...); 40 | char fragment[MAXPACKET]; 41 | char *fragp; 42 | unsigned int rnx,remaining; 43 | }; 44 | 45 | VDESTREAM *vdestream_open(void *opaque, 46 | int fdout, 47 | ssize_t (*frecv)(void *opaque, void *buf, size_t count), 48 | void (*ferr)(void *opaque, int type, char *format, ...) 49 | ) 50 | { 51 | VDESTREAM *vdestream; 52 | if ((vdestream=calloc(1,sizeof(struct vdestream)))==NULL) { 53 | errno=ENOMEM; 54 | return NULL; 55 | } else { 56 | vdestream->opaque=opaque; 57 | vdestream->fdout=fdout; 58 | vdestream->frecv=frecv; 59 | vdestream->ferr=ferr; 60 | return vdestream; 61 | } 62 | } 63 | 64 | ssize_t vdestream_send(VDESTREAM *vdestream, const void *buf, size_t len) 65 | { 66 | if (len <= MAXPACKET) { 67 | unsigned char header[2]; 68 | struct iovec iov[2]={{header,2},{(void *)buf,len}}; 69 | header[0]=len >> 8; 70 | header[1]=len & 0xff; 71 | return writev(vdestream->fdout,iov,2); 72 | } else 73 | return 0; 74 | } 75 | 76 | void vdestream_recv(VDESTREAM *vdestream, unsigned char *buf, size_t len) 77 | { 78 | //fprintf(stderr,"%s: splitpacket rnx=%d remaining=%d size=%d\n",myname,rnx,vdestream->remaining,len); 79 | if (len==0) return; 80 | if (vdestream->rnx>0) { 81 | register int amount=MIN(vdestream->remaining,len); 82 | //fprintf(stderr,"%s: fragment amount %d\n",myname,amount); 83 | memcpy(vdestream->fragp,buf,amount); 84 | vdestream->remaining-=amount; 85 | vdestream->fragp+=amount; 86 | buf+=amount; 87 | len-=amount; 88 | if (vdestream->remaining==0) { 89 | //fprintf(stderr,"%s: delivered defrag %d\n",myname,vdestream->rnx); 90 | vdestream->frecv(vdestream->opaque,vdestream->fragment,vdestream->rnx); 91 | vdestream->rnx=0; 92 | } 93 | } 94 | while (len > 1) { 95 | vdestream->rnx=(buf[0]<<8)+buf[1]; 96 | len-=2; 97 | //fprintf(stderr,"%s %d: packet %d size %d %x %x\n",myname,getpid(),vdestream->rnx,len,buf[0],buf[1]); 98 | buf+=2; 99 | if (vdestream->rnx == 0) 100 | continue; 101 | if (vdestream->rnx > MAXPACKET) { 102 | if (vdestream->ferr != NULL) 103 | vdestream->ferr(vdestream->opaque,PACKET_LENGTH_ERROR, 104 | "size %d expected size %d",len,vdestream->rnx); 105 | vdestream->rnx=0; 106 | return; 107 | } 108 | if (vdestream->rnx > len) { 109 | //fprintf(stderr,"%s: begin defrag %d\n",myname,vdestream->rnx); 110 | vdestream->fragp=vdestream->fragment; 111 | memcpy(vdestream->fragp,buf,len); 112 | vdestream->remaining=vdestream->rnx-len; 113 | vdestream->fragp+=len; 114 | len=0; 115 | } else { 116 | //fprintf(stderr,"%s: deliver %d\n",myname,vdestream->rnx); 117 | vdestream->frecv(vdestream->opaque,buf,vdestream->rnx); 118 | buf+=vdestream->rnx; 119 | len-=vdestream->rnx; 120 | vdestream->rnx=0; 121 | } 122 | } 123 | } 124 | 125 | void vdestream_close(VDESTREAM *vdestream) 126 | { 127 | free(vdestream); 128 | } 129 | 130 | -------------------------------------------------------------------------------- /libvdeplug4/parseparms.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Renzo Davoli, University of Bologna 3 | * 4 | * parse parameters for vdeplug modules. 5 | * 6 | * VDE is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 2 9 | * of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; If not, see . 18 | * 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #if 0 35 | // defined in libvdeplug_mod.h. 36 | struct vdeparms { 37 | char *tag; 38 | char **value; 39 | }; 40 | #endif 41 | static inline int isnumber(const char *s) { 42 | while (1) { 43 | if (!isdigit(*s++)) return 0; /* an empty string is *not* a number */ 44 | if (*s == 0) return 1; 45 | } 46 | } 47 | 48 | unsigned long long strtoullm(const char *numstr) { 49 | char *tail; 50 | unsigned long long rval = strtoull(numstr, &tail, 0); 51 | for (; *tail; tail++) { 52 | switch (*tail) { 53 | case 'k': 54 | case 'K': rval *= 1ULL<<10; break; 55 | case 'm': 56 | case 'M': rval *= 1ULL<<20; break; 57 | case 'g': 58 | case 'G': rval *= 1ULL<<30; break; 59 | case 't': 60 | case 'T': rval *= 1ULL<<40; break; 61 | } 62 | } 63 | return rval; 64 | } 65 | 66 | gid_t vde_grnam2gid(const char *name) { 67 | if (name) { 68 | if (*name == 0) 69 | return getegid(); 70 | else if (isnumber(name)) 71 | return atoi(name); 72 | else { 73 | struct group grp; 74 | struct group *rgrp; 75 | size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); 76 | char buf[buflen]; 77 | getgrnam_r(name, &grp, buf, buflen, &rgrp); 78 | return rgrp ? grp.gr_gid : -1; 79 | } 80 | } 81 | return -1; 82 | } 83 | 84 | #define CHAR 0 85 | #define QUOTE 1 86 | #define DOUBLEQ 2 87 | #define ESC 3 88 | #define PERC 4 89 | #define PER2 5 90 | #define DELIM 6 91 | #define END 7 92 | #define TSIZE (END + 1) 93 | 94 | #define COPY 1 95 | #define CPER 3 96 | 97 | static char nextstate[TSIZE - 1][TSIZE] = { 98 | {CHAR, QUOTE, DOUBLEQ, ESC, PERC, 0, DELIM, END}, 99 | {QUOTE, CHAR, QUOTE, QUOTE, QUOTE, 0, QUOTE, END}, 100 | {DOUBLEQ, DOUBLEQ, CHAR, DOUBLEQ, DOUBLEQ, 0, DOUBLEQ, END}, 101 | {CHAR, CHAR, CHAR, CHAR, CHAR, 0, CHAR, END}, 102 | {PER2, QUOTE, DOUBLEQ, ESC, PERC, 0, DELIM, END}, 103 | {CHAR, QUOTE, DOUBLEQ, ESC, PERC, 0, DELIM, END}, 104 | {CHAR, QUOTE, DOUBLEQ, ESC, PERC, 0, DELIM, END}, 105 | }; 106 | 107 | static char action[TSIZE - 2][TSIZE] = { 108 | {COPY, 0, 0, 0, COPY, 0, 0, 0}, //char 109 | {COPY, 0, COPY, COPY, COPY, 0, COPY, 0}, //quote 110 | {COPY, COPY, 0, COPY, COPY, 0, COPY, 0}, //doubleq 111 | {COPY, COPY, COPY, COPY, COPY, 0, COPY, 0}, //esc 112 | {COPY, 0, 0, 0, COPY, 0, 0, 0}, //perc 113 | {CPER, 0, 0, 0, COPY, 0, 0, 0}, //per2 114 | }; 115 | 116 | static const char *hexchars = "0123456789ABCDEF0123456789abcdef"; 117 | static inline int ch2n(char x) { 118 | char *n = strchr(hexchars, x); 119 | return n ? (n - hexchars) % 16 : -1; 120 | } 121 | 122 | static int token(char c, const char *delim) { 123 | int this; 124 | switch (c) { 125 | case 0: this = END; break; 126 | case '\'': this = QUOTE; break; 127 | case '\"': this = DOUBLEQ; break; 128 | case '\\': this = ESC; break; 129 | case '%': this = PERC; break; 130 | default: this = strchr(delim, c) == NULL ? CHAR : DELIM; 131 | } 132 | return this; 133 | } 134 | 135 | /* like strtok_r(3) + this function supports quoting with ' " and char protection \ */ 136 | static char *strtokq_r(char *s, const char *delim, char **saveptr) { 137 | char *begin, *from, *to; 138 | int status = CHAR; 139 | begin = from = to = (s == NULL) ? *saveptr : s; 140 | if (from == NULL) 141 | return NULL; 142 | while (status != DELIM && status != END) { 143 | int this = token(*from, delim); 144 | int todo = action[status][this]; 145 | // printf("%c %d -> %d\n", *from, status, nextstate[status][this]); 146 | if (todo & COPY) { 147 | *to = *from; 148 | if (todo == CPER) { 149 | char *perc = to - 2; 150 | int hex1 = ch2n(perc[1]); 151 | int hex2 = ch2n(perc[2]); 152 | if (hex1 >= 0 && hex2 >= 0) { 153 | *perc = hex1 * 0x10 + hex2; 154 | to = perc; 155 | } 156 | } 157 | to++; 158 | } 159 | from++; 160 | status = nextstate[status][this]; 161 | } 162 | *to = 0; 163 | *saveptr = (status == END) ? NULL : from; 164 | return begin; 165 | } 166 | 167 | static char *strtokq_nostrip_r(char *s, const char *delim, char **saveptr) { 168 | char *begin, *from, *to; 169 | int status = CHAR; 170 | begin = from = to = (s == NULL) ? *saveptr : s; 171 | if (from == NULL) 172 | return NULL; 173 | while (status != DELIM && status != END) { 174 | int this = token(*from, delim); 175 | if (this != DELIM) to++; 176 | from++; 177 | status = nextstate[status][this]; 178 | } 179 | *to = 0; 180 | *saveptr = (status == END) ? NULL : from; 181 | return begin; 182 | } 183 | 184 | /* this function splits the token using the last (non quoted) occurence of the delimiter */ 185 | static char *strtokq_rev_r(char *s, const char *delim) { 186 | char *begin, *scan, *to; 187 | int status = CHAR; 188 | scan = begin = s; 189 | to = NULL; 190 | if (scan == NULL) 191 | return NULL; 192 | for (;status != END; scan++) { 193 | int this = token(*scan, delim); 194 | status = nextstate[status][this]; 195 | if (status == DELIM) to = scan; 196 | } 197 | if (to != NULL) *to = 0; 198 | return begin; 199 | } 200 | 201 | int vde_parseparms(char *str, struct vdeparms *parms){ 202 | if (*str != 0) { 203 | char *sp; 204 | char *elem; 205 | elem = strtokq_r(str, "/", &sp); 206 | while((elem = strtokq_r(NULL, "/", &sp)) != NULL) { 207 | char *eq = strchr(elem, '='); 208 | int taglen=eq ? eq-elem : strlen(elem); 209 | if (taglen > 0) { 210 | struct vdeparms *scan; 211 | for (scan = parms; scan->tag; scan++) { 212 | if (strncmp(elem, scan->tag, taglen) == 0) { 213 | *(scan->value)=eq ? eq+1 : ""; 214 | break; 215 | } 216 | } 217 | if (scan->tag == NULL) { 218 | fprintf(stderr, "unknown key: %*.*s\n", taglen, taglen, elem); 219 | errno = EINVAL; 220 | return -1; 221 | } 222 | } 223 | } 224 | } 225 | return 0; 226 | } 227 | 228 | int vde_parsepathparms(char *str, struct vdeparms *parms){ 229 | if (*str != 0) { 230 | char *sp; 231 | char *elem; 232 | char *bracket; 233 | elem = strtokq_r(str, "[", &sp); 234 | for (bracket = strtokq_rev_r(sp, "]"); 235 | (elem = strtokq_r(bracket, "/", &sp)) != NULL; bracket = NULL) { 236 | char *eq = strchr(elem, '='); 237 | int taglen=eq ? eq-elem : strlen(elem); 238 | if (taglen > 0) { 239 | struct vdeparms *scan; 240 | for (scan = parms; scan->tag; scan++) { 241 | if (strncmp(elem, scan->tag, taglen) == 0) { 242 | *(scan->value)=eq ? eq+1 : ""; 243 | break; 244 | } 245 | } 246 | if (scan->tag == NULL) { 247 | if (eq == NULL && parms->tag != NULL && parms->tag[0] == 0) 248 | *(parms->value) = elem; 249 | else { 250 | fprintf(stderr, "unknown key: %*.*s\n", taglen, taglen, elem); 251 | errno = EINVAL; 252 | return -1; 253 | } 254 | } 255 | } 256 | } 257 | } 258 | return 0; 259 | } 260 | 261 | char *vde_parsenestparms(char *str){ 262 | if (*str != 0) { 263 | char *sp; 264 | char *bracket; 265 | strtokq_nostrip_r(str, "{", &sp); 266 | bracket = strtokq_rev_r(sp, "}"); 267 | return bracket; 268 | } 269 | return NULL; 270 | } 271 | 272 | #if 0 273 | int main(int argc, char *argv[]) { 274 | char *portstr="12345"; 275 | char *vnistr="1"; 276 | char *ttlstr="1"; 277 | struct vdeparms parms[] = {{"port", &portstr}, {"vni", &vnistr}, {"ttl", &ttlstr}, {NULL, NULL}}; 278 | 279 | printf("%s\n", argv[1]); 280 | vde_parseparms(argv[1], parms); 281 | printf("%s\n", argv[1]); 282 | 283 | struct vdeparms *scan; 284 | for (scan = parms; scan->tag; scan++) 285 | printf("%s %s\n", scan->tag, *(scan->value)); 286 | } 287 | #endif 288 | -------------------------------------------------------------------------------- /libvdeplug4/vde_hashtable.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct vde_hashtable { 9 | size_t payload_size; 10 | unsigned int hash_mask; 11 | uint64_t seed; 12 | /* plus the table here */ 13 | char ht[]; 14 | }; 15 | 16 | struct ht_elem { 17 | uint64_t edst; 18 | time_t last_seen; 19 | char payload[]; 20 | }; 21 | #define sizeof_ht_elem(payload_size) (sizeof(struct ht_elem) + payload_size) 22 | 23 | static inline __attribute__((always_inline)) struct ht_elem *ht_get(struct vde_hashtable *table, int index) { 24 | return (void *) (table->ht + index * sizeof_ht_elem(table->payload_size)); 25 | } 26 | 27 | static inline __attribute__((always_inline)) int calc_hash(uint64_t src, unsigned int hash_mask, uint64_t seed) 28 | { 29 | src ^= src >> 33 ^ seed; 30 | src *= 0xff51afd7ed558ccd; 31 | src ^= src >> 33; 32 | src *= 0xc4ceb9fe1a85ec53; 33 | src ^= src >> 33; 34 | return src & hash_mask; 35 | } 36 | 37 | #define extmac(MAC,VLAN) \ 38 | ((*(uint32_t *) &((MAC)[0])) + ((uint64_t) ((*(uint16_t *) &((MAC)[4]))+ ((uint64_t) (VLAN) << 16)) << 32)) 39 | 40 | 41 | /* look in global hash table for given address, and return associated address */ 42 | void *vde_find_in_hash(struct vde_hashtable *table, unsigned char *dst, int vlan, time_t too_old) 43 | { 44 | if (__builtin_expect(table == NULL, 0)) 45 | return NULL; 46 | else { 47 | uint64_t edst; 48 | int index; 49 | struct ht_elem *entry; 50 | 51 | if ((dst[0] & 1) == 1) /* broadcast */ 52 | return NULL; 53 | edst = extmac(dst,vlan); 54 | index = calc_hash(edst, table->hash_mask, table->seed); 55 | //printf("index %d\n",index); 56 | entry = ht_get(table, index); 57 | if (entry->edst == edst && entry->last_seen >= too_old) 58 | return &(entry->payload); 59 | else 60 | return NULL; 61 | } 62 | } 63 | 64 | void vde_find_in_hash_update(struct vde_hashtable *table, unsigned char *src, int vlan, void *payload, time_t now) 65 | { 66 | if (__builtin_expect(table == NULL, 0)) 67 | return; 68 | else { 69 | uint64_t esrc; 70 | int index; 71 | struct ht_elem *entry; 72 | 73 | if ((src[0] & 1) == 1) /* broadcast */ 74 | return; 75 | 76 | esrc = extmac(src,vlan); 77 | index = calc_hash(esrc, table->hash_mask, table->seed); 78 | //printf("index %d\n",index); 79 | 80 | entry = ht_get(table, index); 81 | entry->edst = esrc; 82 | memcpy(&(entry->payload),payload,table->payload_size); 83 | entry->last_seen = now; 84 | } 85 | } 86 | 87 | void vde_hash_delete(struct vde_hashtable *table, void *payload) 88 | { 89 | if (__builtin_expect(table == NULL, 0)) 90 | return; 91 | else { 92 | unsigned int i; 93 | for (i = 0; i < table->hash_mask + 1; i++) { 94 | struct ht_elem *entry = ht_get(table, i); 95 | if (memcmp(entry->payload, payload, table->payload_size) == 0) 96 | entry->last_seen = 0; 97 | } 98 | } 99 | } 100 | 101 | // #define vde_hash_init(type, hash_mask, seed) _vde_hash_init(sizeof(type), (hash_mask), (seed)) 102 | 103 | struct vde_hashtable *_vde_hash_init(size_t payload_size, unsigned int hashsize, uint64_t seed) 104 | { 105 | struct vde_hashtable *retval; 106 | if (hashsize == 0) 107 | return NULL; 108 | hashsize = (2 << (sizeof(hashsize) * 8 - __builtin_clz(hashsize - 1) - 1)); 109 | 110 | retval = calloc(1, sizeof(struct vde_hashtable) 111 | + hashsize * sizeof_ht_elem(payload_size)); 112 | if (retval) { 113 | retval->payload_size = payload_size; 114 | retval->hash_mask = hashsize - 1; 115 | retval->seed = seed; 116 | } 117 | return retval; 118 | } 119 | 120 | void vde_hash_fini(struct vde_hashtable *table) 121 | { 122 | free(table); 123 | } 124 | 125 | #if 0 126 | int main() { 127 | struct vde_hashtable *ht = vde_hash_init(int, 15, 0); 128 | 129 | while(1) { 130 | unsigned char mac[7]; 131 | unsigned int port; 132 | scanf("%6s %u",mac,&port); 133 | printf("%s %d \n",mac,port); 134 | if (port == 0) { 135 | int *pport = vde_find_in_hash(ht, mac, 0, time(NULL)-20); 136 | if (pport) 137 | printf("-> %d\n", *pport); 138 | else 139 | printf("-> not found\n"); 140 | } else 141 | vde_find_in_hash_update(ht, mac, 0, &port, time(NULL)); 142 | } 143 | } 144 | #endif 145 | -------------------------------------------------------------------------------- /libvdeplug4_static/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | add_library(libvdeplug_a STATIC libvdeplug.c) 4 | set_target_properties(libvdeplug_a PROPERTIES OUTPUT_NAME vdeplug) 5 | 6 | install( 7 | TARGETS libvdeplug_a 8 | ARCHIVE 9 | DESTINATION ${CMAKE_INSTALL_LIBDIR} 10 | ) 11 | -------------------------------------------------------------------------------- /libvdeplug4_static/libvdeplug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libvdeplug - A library to connect to a VDE Switch. 3 | * static library (using vde_plug as a helper) 4 | * Copyright (C) 2019 Renzo Davoli, University of Bologna 5 | * 6 | * This library is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation version 2.1 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 14 | * General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 | */ 20 | 21 | #define _GNU_SOURCE 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | struct vdeconn { 36 | int fddata; 37 | }; 38 | 39 | /* enough char to store an int type */ 40 | #define ENOUGH(type) ((CHAR_BIT * sizeof(type) - 1) / 3 + 2) 41 | #define ENOUGH_OCTAL(type) ((CHAR_BIT * sizeof(type) + 2) / 3) 42 | /* vde_plug --descr xx --port2 xx --mod2 xx --group2 xx seqpacket://NN vdeurl (NULL) */ 43 | #define VDE_MAX_ARGC 12 44 | #define SEQPACKET_HEAD "seqpacket://" 45 | #define SEQPACKET_HEAD_LEN (sizeof(SEQPACKET_HEAD) - 1) 46 | #define DEFAULT_DESCRIPTION "libvdeplug" 47 | #define CHILDSTACKSIZE 4096 48 | 49 | #define err_goto(err, label) do { \ 50 | (err) = errno; \ 51 | goto label; \ 52 | } while(0) 53 | 54 | struct child_data { 55 | char **argv; 56 | int fd; 57 | }; 58 | 59 | static int child(void *arg) { 60 | struct child_data *data = arg; 61 | int err; 62 | execvp(data->argv[0], data->argv); 63 | err = errno; 64 | write(data->fd, &err, sizeof(err)); 65 | close(data->fd); 66 | return 0; 67 | } 68 | 69 | VDECONN *vde_open_real(char *given_vde_url, char *descr,int interface_version, 70 | struct vde_open_args *open_args) 71 | { 72 | int sv[2]; 73 | struct vdeconn *conn; 74 | char *description = (descr != NULL && *descr != 0) ? descr : DEFAULT_DESCRIPTION; 75 | char *vde_url = (given_vde_url == NULL) ? "" : given_vde_url; 76 | char seqpacketurl[SEQPACKET_HEAD_LEN + ENOUGH(int) + 1] = SEQPACKET_HEAD; 77 | char port_str[ENOUGH(int) + 1]; 78 | char mode_str[ENOUGH_OCTAL(mode_t) + 2]; 79 | char *argv[VDE_MAX_ARGC] = {"vde_plug", "--descr", description, seqpacketurl, vde_url, NULL}; 80 | int argc = 3; 81 | int rv, err; 82 | struct child_data data; 83 | char childstack[CHILDSTACKSIZE]; 84 | int fds[2]; 85 | int pid; 86 | 87 | if (open_args != NULL) { 88 | if (open_args->port != 0) { 89 | snprintf(port_str, ENOUGH(int) + 1, "%d", open_args->port); 90 | argv[argc++] = "--port2"; 91 | argv[argc++] = port_str; 92 | } 93 | if (open_args->group != 0) { 94 | argv[argc++] = "--group2"; 95 | argv[argc++] = open_args->group; 96 | } 97 | if (open_args->mode != 0) { 98 | snprintf(mode_str, ENOUGH_OCTAL(mode_t) + 2, "0%o", open_args->mode); 99 | argv[argc++] = "--mod2"; 100 | argv[argc++] = mode_str; 101 | } 102 | } 103 | argv[argc++] = seqpacketurl; 104 | argv[argc++] = vde_url; 105 | argv[argc++] = NULL; 106 | 107 | /* synch socketpair: fds[0] is for the parent, fds[1] is 108 | close_on_exec inherited by the child */ 109 | rv = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 110 | if (rv < 0) 111 | err_goto(err, leave); 112 | data.argv = argv; 113 | data.fd = fds[1]; 114 | 115 | rv = fcntl(fds[1], F_SETFD, FD_CLOEXEC); 116 | if (rv < 0) 117 | err_goto(err, close_fds); 118 | 119 | /* This socketpair is for vde packets: sv[0] is for the parent (e.g. User-Mode Linux) 120 | sv[1] is forthe helper command (vde_plug) */ 121 | rv = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv); 122 | if (rv < 0) 123 | err_goto(err, close_fds); 124 | 125 | rv = fcntl(sv[0], F_SETFD, FD_CLOEXEC); 126 | if (rv < 0) 127 | err_goto(err, close_sv); 128 | 129 | conn = (VDECONN *) malloc(sizeof(VDECONN)); 130 | if (conn == NULL) 131 | err_goto(err, close_sv); 132 | 133 | snprintf(seqpacketurl + SEQPACKET_HEAD_LEN, SEQPACKET_HEAD_LEN, "%d", sv[1]); 134 | 135 | /* use clone instead of fork. User-mode linux cannot fork */ 136 | pid = clone(child, (void *) (childstack + CHILDSTACKSIZE), 137 | CLONE_VM, &data); 138 | if (pid < 0) 139 | err_goto(err, free_conn); 140 | 141 | /* close the descriptors used by the child */ 142 | close(fds[1]); 143 | close(sv[1]); 144 | conn->fddata = sv[0]; 145 | 146 | /* wait for child's execvp */ 147 | rv = read(fds[0], &err, sizeof(err)); 148 | close(fds[0]); 149 | if (rv > 0) { 150 | close(sv[0]); 151 | free(conn); 152 | errno = err; 153 | return NULL; 154 | } else 155 | return conn; 156 | 157 | free_conn: 158 | free(conn); 159 | close_sv: 160 | close(sv[0]); 161 | close(sv[1]); 162 | close_fds: 163 | close(fds[0]); 164 | close(fds[1]); 165 | leave: 166 | errno = err; 167 | return NULL; 168 | } 169 | 170 | ssize_t vde_recv(VDECONN *conn,void *buf,size_t len,int flags) 171 | { 172 | if (__builtin_expect(conn!=0,1)) 173 | return recv(conn->fddata,buf,len,0); 174 | else { 175 | errno=EBADF; 176 | return -1; 177 | } 178 | } 179 | 180 | ssize_t vde_send(VDECONN *conn,const void *buf,size_t len,int flags) 181 | { 182 | if (__builtin_expect(conn!=0,1)) { 183 | /* never send zero length packets */ 184 | if (__builtin_expect(len > 0, 1)) 185 | return send(conn->fddata,buf,len,0); 186 | else 187 | return len; 188 | } else { 189 | errno=EBADF; 190 | return -1; 191 | } 192 | } 193 | 194 | int vde_datafd(VDECONN *conn) 195 | { 196 | if (__builtin_expect(conn!=0,1)) 197 | return conn->fddata; 198 | else { 199 | errno=EBADF; 200 | return -1; 201 | } 202 | } 203 | 204 | int vde_ctlfd(VDECONN *conn) 205 | { 206 | return -1; 207 | } 208 | 209 | int vde_close(VDECONN *conn) 210 | { 211 | if (__builtin_expect(conn!=0,1)) { 212 | return close(conn->fddata); 213 | } else { 214 | errno=EBADF; 215 | return -1; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /man/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7) 2 | 3 | set(PANDOC_ORG "VirtualSquare") 4 | 5 | # ### pandoc pages 6 | 7 | file(GLOB VU_PANDOC_PAGES ${CMAKE_CURRENT_SOURCE_DIR}/*.[1-8].md) 8 | set(VU_MAN_FILES) 9 | foreach(VU_PANDOC_PATH IN LISTS VU_PANDOC_PAGES) 10 | # VU_PANDOCPAGE: basename of VU_PANDOC_PATH 11 | get_filename_component(VU_PANDOCPAGE ${VU_PANDOC_PATH} NAME) 12 | # VU_MANPAGE: VU_PANDOCPAGE without the suffix 13 | string(REGEX REPLACE "\.md$" "" VU_MANPAGE ${VU_PANDOCPAGE}) 14 | list(APPEND VU_MAN_FILES ${VU_MANPAGE}) 15 | endforeach(VU_PANDOC_PATH) 16 | 17 | add_custom_target(${PROJECT_NAME}_manpages ALL make PANDOC_ORG="${PANDOC_ORG}" ${VU_MAN_FILES} 18 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 19 | 20 | ### man pages 21 | file(GLOB VU_MAN_PAGES ${CMAKE_CURRENT_SOURCE_DIR}/*.[1-8]) 22 | foreach(VU_MAN_PATH IN LISTS VU_MAN_PAGES) 23 | get_filename_component(VU_MANPAGE ${VU_MAN_PATH} NAME) 24 | string(REGEX REPLACE ".*\\." "" MAN_CHAPTER ${VU_MANPAGE}) 25 | install(FILES ${VU_MAN_PATH} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_CHAPTER}) 26 | endforeach(VU_MAN_PATH) 27 | -------------------------------------------------------------------------------- /man/Makefile: -------------------------------------------------------------------------------- 1 | MAKEFLAGS += --silent 2 | PANDOC=pandoc 3 | PANDOCOK := $(shell command -v ${PANDOC} 2> /dev/null) 4 | PANDOCMINVER=3.1.7 5 | 6 | ifdef PANDOCOK 7 | PANDOCVER := $(shell ${PANDOC} -v | head -1 | cut -d ' ' -f 2) 8 | PANDOCVEROK := $(shell printf '%s\n' ${PANDOCMINVER} ${PANDOCVER} | sort -C -V; echo $$?) 9 | endif 10 | 11 | none: 12 | 13 | % : %.md 14 | ifdef PANDOCOK 15 | ifeq (${PANDOCVEROK}, 1) 16 | echo "${PANDOC} ${PANDOCVER} < ${PANDOCMINVER}. $@ can create font warnings with man/groff" >/dev/stderr >&2 17 | endif 18 | # copy copyright notice 19 | grep "^\.\\\\\"" $< > $@ || true 20 | # run pandoc 21 | $(eval SECTION := $(subst .,,$(suffix $@))) 22 | $(eval BASENAME := $(basename $@)) 23 | $(eval TITLE := $(shell echo "${BASENAME}\(${SECTION}\)" | tr [:lower:] [:upper:])) 24 | $(eval HEADER := "$(shell man ${SECTION} intro | head -1 | sed -e 's/^[^[:blank:]]*[[:blank:]]*//' -e 's/[[:blank:]]*[^[:blank:]]*$$//' )") 25 | $(PANDOC) -standalone -M title=${TITLE} -M section=${SECTION} -M header=${HEADER} -M footer=${PANDOC_ORG} -M "date=`date +\"%B %Y\"`" --to man $< >> $@ 26 | # workaround for boldface rendering 27 | sed -i -e 's/\\f\[CR\]/\\f\[CB\]/g' $@ || true 28 | echo "$@ manpage updated" >/dev/stderr >&2 29 | else 30 | echo "${PANDOC} is not available. Manpage $@ cannot be updated" >/dev/stderr >&2 31 | endif 32 | -------------------------------------------------------------------------------- /man/dpipe.1: -------------------------------------------------------------------------------- 1 | .TH DPIPE 1 "August 23, 2016" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | dpipe \- bi-directional pipe command 4 | .SH SYNOPSIS 5 | .B dpipe 6 | [ 7 | .I OPTIONS 8 | ] 9 | .I command 10 | [ 11 | .I args 12 | ] 13 | .BI = 14 | .I command 15 | [ 16 | .I args 17 | ] 18 | [ 19 | .BI = 20 | [ 21 | .I command 22 | [ 23 | .I args 24 | ] 25 | ] 26 | ] 27 | \&... 28 | .br 29 | .SH DESCRIPTION 30 | \fBdpipe\fP is a general tool to run two commands diverting the 31 | standard output of the first command into the standard input of the second 32 | and vice-versa. 33 | It is the bi-directional 34 | extension of the \fB|\fP (pipe) syntax used by all the shells. 35 | The \fB=\fP has been chosen as a metaphor of two parallel communication lines 36 | between the commands. 37 | It is also possible to concatenate several tools. Intermediate programs communicate 38 | using standard input and standard output with the preceding tool and alternate standard input 39 | and output towards the following tool. 40 | The number of the file descriptors is use as alternate standard input and output can be retrieved 41 | from the envirnonment variables ALTERNATE_STDIN and ALTERNATE_STDOUT using \fBgetenv(3)\fR or \fBgetenv(1)\fR. 42 | If an intermediate tool should process only the data flowing in one direction 43 | use \fB{\fP or \fB}\fP 44 | as suffix for the preceding \fB=\fP and prefix of the following one. 45 | .br 46 | This tool has been written as a tool for the Virtual Distributed Ethernet. 47 | .SH OPTIONS 48 | .B dpipe 49 | accepts the following options: 50 | .TP 51 | \fB\-n 52 | .TQ 53 | \fB\-\-nowrapproc 54 | create only one process per command, the last one being the parent of all the others 55 | (the standard behavior of dpipe is to create a process for dpipe and all the 56 | processes running the commands are children of dpipe). 57 | .TP 58 | \fB\-d 59 | .TQ 60 | \fB\-\-daemon 61 | run as a daemon. 62 | .TP 63 | \fB\-p\fR \fIPIDFILE 64 | .TQ 65 | \fB\-\-pidfile\fR \fIPIDFILE 66 | write the process id of the dpipe process (or the id of the last command if \fB-r\fR) 67 | to the file \fIPIDFILE\fR 68 | .TP 69 | \fB\-P\fR \fIPGRPFILE 70 | .TQ 71 | \fB\-\-pgrpfile\fR \fIPGRPFILE 72 | write the process group id (negative) including all the processes launched by dpipe 73 | to the file \fIPGRPFILE\fR 74 | .TP 75 | \fB\-N 76 | .TQ 77 | \fB\-\-nowrapnoclean 78 | Like -n but it does not remove PIDFILE or PGRPFILE. 79 | (when \fB-n\fR is used together with \fB-p\fR or \fB-P\fR, dpipe creates a cleanup process 80 | to wait for the processes to terminate and remove the files. \fB-N\fR avoids the creation 81 | of the cleanup process) 82 | .SH EXAMPLES 83 | .B dpipe a = b 84 | .br 85 | processes a and b are bidirectionally connected: stdin of a is connected to stdout of b 86 | and vice-versa 87 | .br 88 | .B dpipe a = b = c 89 | .br 90 | a and b are connected as above. Alternate stdin of b is connected to stdout of c and 91 | alternate stdout of b to stdin of c 92 | .br 93 | .B dpipe a =} b }= c 94 | .br 95 | This is a cycle of pipes: stdout of a is connected to stdin of b, stdout of b with stdin 96 | of c, and stdout of c to stdin of a 97 | .br 98 | .B dpipe a =} b }={ c {= d = e 99 | .br 100 | all the notations can be mixed together. 101 | this is a -> b -> d -> c and back to a; alternate ports of d are connected to e 102 | .SH NOTICE 103 | Virtual Distributed Ethernet is not related in any way with 104 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 105 | i.e. the German "Association for Electrical, Electronic & Information 106 | Technologies"). 107 | .SH SEE ALSO 108 | \fBvde_switch\fP(1), 109 | \fBvde_plug\fP(1), 110 | \fBvde_plug2tap\fP(1), 111 | \fBvdeq\fP(1). 112 | \fBwirefilter\fP(1). 113 | .br 114 | .SH AUTHOR 115 | VDE is a project by Renzo Davoli . 116 | -------------------------------------------------------------------------------- /man/libvdeplug.3: -------------------------------------------------------------------------------- 1 | .\"* libvdeplug: a network namespace as a user library 2 | .\" Copyright (C) 2017 Renzo Davoli. University of Bologna. 3 | .\" 4 | .\" This library is free software; you can redistribute it and/or 5 | .\" modify it under the terms of the GNU Lesser General Public 6 | .\" License as published by the Free Software Foundation; either 7 | .\" version 2.1 of the License, or (at your option) any later version. 8 | .\" 9 | .\" This library is distributed in the hope that it will be useful, 10 | .\" but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | .\" Lesser General Public License for more details. 13 | .\" 14 | .\" You should have received a copy of the GNU Lesser General Public 15 | .\" License along with this library; if not, write to the Free Software 16 | .\" Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | 18 | .TH libvdeplug 3 2017-05-21 "VirtualSquare" "Linux Programmer's Manual" 19 | .SH NAME 20 | vde_open, vde_recv, vde_send, vde_send, vde_recv, vde_close \- connect clients to a VDE (virtual distributed ethernet) network 21 | .SH SYNOPSIS 22 | .B #include 23 | .br 24 | .BI "VDECONN *vde_open(char *vnl,char *descr, struct vde_open_args *open_args);" 25 | .br 26 | .BI "ssize_t vde_recv(VDECONN *conn,void *buf,size_t len,int flags);" 27 | .br 28 | .BI "ssize_t vde_send(VDECONN *conn,const void *buf,size_t len,int flags);" 29 | .br 30 | .BI "int vde_datafd(VDECONN *conn);" 31 | .br 32 | .BI "int vde_ctlfd(VDECONN *conn);" 33 | .br 34 | .BI "int vde_close(VDECONN *conn);" 35 | .sp 36 | These functions are provided by libvdeplug. Link with \fI-lvdeplug\fR. 37 | .SH DESCRIPTION 38 | Libvdeplug is the library used by clients to join a VDE network. It is a generic library which can 39 | use several different implementations for virtual distributed networks. In fact the Virtual Network Locator (VNL) \fIvnl\fR 40 | has the syntax \fImodule\fB://\fIspecific_address\fR. 41 | e.g. \fBvde:///home/user/myswitch\fR or \fBvxvde://239.0.0.1\fR. 42 | The default module is \fBlibvdeplug_vde(1)\fR (connection to a \fBvde_switch(1)\fR) 43 | and can be omitted. e.g. \fB/home/user/myswitch\fR means 44 | \fBvde:///home/user/myswitch\fR 45 | 46 | \fBvde_open\fR opens a VDE connection: \fIvnl\fR is the vde network identifier as described here above 47 | and \fIdescr\fR is a description of this connection (it can be useful to identify this connection in 48 | the port list of a switch). \fRopen_args\fR has been left for backwards compatibility but can be safely 49 | set to NULL as all the options previosly defined as fields of \fIstruct vde_open_args\fR are now 50 | parameters of the VDE modules (can be defined using a module specific syntax in VNL). 51 | 52 | \fBvde_recv\fR receives a packet from the VDE connection. 53 | 54 | \fBvde_send\fR sends a packet to the VDE connection. 55 | 56 | \fBvde_datafd\fR returns the data file descriptor of the connection: this descriptor can be used in 57 | \fBpoll(2)\fR or \fBselect(2)\fR (or similar) system calls. When this descriptor signals data available for reading 58 | \fBvde_recv\fR will not block. 59 | 60 | \fBvde_ctlfd\fR returns the control file descriptor of the connection. Not all the modules support control 61 | descritors, but when it is valid descriptor (greater or equal than 0) can be used to check if the remote 62 | endpoint (switch or peer) hanged up. No data can be sent or received using the control file descriptor, 63 | it returns an end-of-file condition when the connection get closed (zero length on reading). 64 | 65 | \fBvde_close\fR closes a vde connections. 66 | 67 | .SH RETURN VALUE 68 | \fBvde_open\fR returns the descriptor of the VDE connection which is used as a parameter of all the other functions. 69 | NULL is returned in case of error. 70 | 71 | \fBvde_recv\fR returns the length of the packet received. It should never be less then 14 bytes (the length of 72 | an ethernet header). It returns -1 in case of error, it may return 1 to notify that a packet has been 73 | received but it must be dropped (e.g. the sender was not allowed to send that packet). 74 | 75 | \fBvde_send\fR returns the number of bytes sent. It returns -1 in case of error. 76 | 77 | \fBvde_datafd\fR and \fBvde_ctlfd\fR returns a file descriptor and -1 in case of error. 78 | 79 | \fBvde_datafd\fR returns 0 in case of success and -1 in case of error. 80 | 81 | .SH NOTICE 82 | Virtual Distributed Ethernet is not related in any way with 83 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 84 | i.e. the German "Association for Electrical, Electronic & Information 85 | Technologies"). 86 | 87 | .SH SEE ALSO 88 | \fBvde_plug\fR(1), 89 | \fBvde_switch\fR(1) 90 | 91 | .SH BUGS 92 | Bug reports should be addressed to 93 | .SH AUTHOR 94 | Renzo Davoli 95 | -------------------------------------------------------------------------------- /man/libvdeplug_bonding.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_BONDING 1 "April 30, 2017" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_bonding - multiplexing vdeplug module: bonding links 4 | .SH SYNOPSIS 5 | libvdeplug_bonding.so 6 | .SH DESCRIPTION 7 | This is a libvdeplug multiplex module implementing the bonding of multiple links. 8 | 9 | The common usage of this module is to support multiple links between virtual machines or switches. 10 | This module transmit packets on all the available links in a round-robin manner. 11 | If the links use several paths and channels it is possible to reach a higher bandwidth. 12 | 13 | This module of libvdeplug4 can be used in any program supporting vde like 14 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 15 | 16 | The vde_plug_url syntax of this module is the following: 17 | .RS 18 | .B bonding://\fR[\fIpath\fR] 19 | .br 20 | .B bonding://\fR[\fIpath\fR]\fB[\fR[\fIOPTION\fR][\fB/\fIOPTION\fR][\fB/\fIOPTION\fR]...\fB] 21 | .br 22 | .RE 23 | 24 | If \fIpath\fR is omitted the path of the bonding is /tmp/vdenode_$USERNAME (e.g. /tmp/vdenode_john 25 | if the username is john). 26 | 27 | .SH OPTIONS 28 | .TP 29 | \fBmode=\fR\fIMODE 30 | define the permissions for the bonding node (see chmod). MODE is an octal number. 31 | The standard permission mask is: 0600 (only processes owning to the same user can join the network). 32 | .TP 33 | \fBdirmode=\fR\fIDIRMODE 34 | define the permissions for the bonding node control directory(see chmod). MODE is an octal number. 35 | If omitted, is computed from mode. 36 | .TP 37 | \fBgrp=\fR\fIGROUP 38 | define the group ownership of the bonding node. 39 | .SH EXAMPLES 40 | .B bonding:///tmp/bonding 41 | .br 42 | Other virtual machines, namespaces or vde_plug can join this bondinglink using \fBvde:///tmp/hub\fR or simply \fB/tmp/hub\fR 43 | .br 44 | Given two virtual machines using \fBbonding:///tmp/vm1\fR and \fBbonding:///tmp/vm2\fR respectively, it is possible to 45 | connect them using \fBvde_plug /tmp/vm1 /tmp/vm2\fR. If the second virtual machine is running on a remote hosts; 46 | \fBip1.vm2.domain.org\fR and \fBip2.vm2.domain.org\fR are two ip addresses permitting to reach that remote host using 47 | different paths, the commands \fBvde_plug /tmp/vm1 = ssh ip1.vm2.domain.org vde_plug /tmp/vm2\fR 48 | and \fBvde_plug /tmp/vm1 = ssh ip2.vm2.domain.org vde_plug /tmp/vm2\fR create two channels between the two virtual machines. 49 | Packets are sent in turns on one or the other link. 50 | .br 51 | .B bonding:///tmp/bonding[mode=0666] 52 | .br 53 | It is the same bondinglink, but everybody is allowed to connect their processes. 54 | .SH NOTICE 55 | Virtual Distributed Ethernet is not related in any way with 56 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 57 | i.e. the German "Association for Electrical, Electronic & Information 58 | Technologies"). 59 | .SH SEE ALSO 60 | \fBvde_plug\fP(1), 61 | -------------------------------------------------------------------------------- /man/libvdeplug_cmd.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_CMD 1 "August 23, 2016" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_cmd - vdeplug module: stream a VDE network through a command 4 | .SH SYNOPSIS 5 | libvdeplug_cmd.so 6 | .SH DESCRIPTION 7 | This is the standard vdeplug module to stream a VDE network using a command. 8 | This module of libvdeplug4 can be used in any program supporting vde like 9 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 10 | 11 | The vde_plug_url syntax of this module is the following: 12 | .RS 13 | .br 14 | \fBcmd://\fIcommand\fR 15 | .RE 16 | 17 | .SH EXAMPLES 18 | Appropriate shell quoting is needed. 19 | 20 | .B cmd://"ssh remote.host.org vde_plug vxvde://" 21 | .br 22 | .B kvm .... -net vde,sock=cmd://"ssh remote.host.org vde_plug vxvde://" ... 23 | .br 24 | 25 | In these cases ssh should have been configured to require no foreground authentication 26 | (see how to set up public key authentication: ssh(1) and ssh-keygen(1)). 27 | 28 | .SH NOTICE 29 | Virtual Distributed Ethernet is not related in any way with 30 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 31 | i.e. the German "Association for Electrical, Electronic & Information 32 | Technologies"). 33 | .SH SEE ALSO 34 | \fBvde_plug\fP(1), 35 | -------------------------------------------------------------------------------- /man/libvdeplug_hub.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_HUB 1 "April 30, 2017" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_hub - multiplexing vdeplug module: hub 4 | .SH SYNOPSIS 5 | libvdeplug_hub.so 6 | .SH DESCRIPTION 7 | This is a libvdeplug multiplex module implementing a virtual networking hub. 8 | 9 | This module of libvdeplug4 can be used in any program supporting vde like 10 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 11 | 12 | The vde_plug_url syntax of this module is the following: 13 | .RS 14 | .B hub://\fR[\fIpath\fR] 15 | .br 16 | .B hub://\fR[\fIpath\fR]\fB[\fR[\fIOPTION\fR][\fB/\fIOPTION\fR][\fB/\fIOPTION\fR]...\fB] 17 | .br 18 | .RE 19 | 20 | If \fIpath\fR is omitted the path of the hub is /tmp/vdenode_$USERNAME (e.g. /tmp/vdenode_john 21 | if the username is john). 22 | 23 | .SH OPTIONS 24 | .TP 25 | \fBmode=\fR\fIMODE 26 | define the permissions for the hub (see chmod). MODE is an octal number. 27 | The standard permission mask is: 0600 (only processes owning to the same user can join the network). 28 | .TP 29 | \fBdirmode=\fR\fIDIRMODE 30 | define the permissions for the hub control directory(see chmod). MODE is an octal number. 31 | If omitted, is computed from mode. 32 | .TP 33 | \fBgrp=\fR\fIGROUP 34 | define the group ownership of the hub. 35 | .SH EXAMPLES 36 | .B hub:///tmp/hub 37 | .br 38 | Other virtual machines, namespaces or vde_plug can join this hub using \fBvde:///tmp/hub\fR or simply \fB/tmp/hub\fR 39 | .br 40 | .B hub:///tmp/hub[mode=0666] 41 | .br 42 | It is the same hub, but everybody is allowed to connect their processes. 43 | .SH NOTICE 44 | Virtual Distributed Ethernet is not related in any way with 45 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 46 | i.e. the German "Association for Electrical, Electronic & Information 47 | Technologies"). 48 | .SH SEE ALSO 49 | \fBvde_plug\fP(1), 50 | -------------------------------------------------------------------------------- /man/libvdeplug_macvtap.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_MACVTAP 1 "August 18, 2023" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_macvtap - vdeplug module: macvtap interface 4 | .SH SYNOPSIS 5 | libvdeplug_macvtap.so 6 | .SH DESCRIPTION 7 | This is the standard vdeplug module to connect a MACVTAP interface. 8 | This module of libvdeplug4 can be used in any program supporting vde like 9 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 10 | \fBtunctl\fR or \fBvde_tunctl\fR can be used to preconfigure a TAP device for use by a particular user. 11 | 12 | The vde_plug_url syntax of this module is the following: 13 | .RS 14 | .br 15 | \fBmacvtap://\fImacvtap_interface_name\fR 16 | .RE 17 | 18 | .SH EXAMPLES 19 | .B macvtap://macvlan0 20 | .br 21 | This vde_plug_url refers the macvtap interface named \fBmacvlan0\fR, for instance created by 22 | the command: 23 | .br 24 | .B ip link add link eth0 name macvlan0 type macvtap mode bridge 25 | 26 | .SH NOTICE 27 | Virtual Distributed Ethernet is not related in any way with 28 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 29 | i.e. the German "Association for Electrical, Electronic & Information 30 | Technologies"). 31 | .SH SEE ALSO 32 | \fBvde_plug\fP(1), 33 | -------------------------------------------------------------------------------- /man/libvdeplug_multi.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_MULTI 1 "April 30, 2017" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_multi - multiplexing vdeplug module: multilink 4 | .SH SYNOPSIS 5 | libvdeplug_multi.so 6 | .SH DESCRIPTION 7 | This is a libvdeplug multiplex module implementing a multilink. 8 | 9 | The common usage of this module is to support (usually temporary) multiple links between 10 | virtual machines or switches. This module can be used to implement hand-offs betweek links: 11 | a new link can be set-up and then the old one is closed. 12 | When both links are active, packets can be duplicated. 13 | 14 | This module of libvdeplug4 can be used in any program supporting vde like 15 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 16 | 17 | The vde_plug_url syntax of this module is the following: 18 | .RS 19 | .B multi://\fR[\fIpath\fR] 20 | .br 21 | .B multi://\fR[\fIpath\fR]\fB[\fR[\fIOPTION\fR][\fB/\fIOPTION\fR][\fB/\fIOPTION\fR]...\fB] 22 | .br 23 | .RE 24 | 25 | If \fIpath\fR is omitted the path of the multi is /tmp/vdenode_$USERNAME (e.g. /tmp/vdenode_john 26 | if the username is john). 27 | 28 | .SH OPTIONS 29 | .TP 30 | \fBmode=\fR\fIMODE 31 | define the permissions for the multilink (see chmod). MODE is an octal number. 32 | The standard permission mask is: 0600 (only processes owning to the same user can join the network). 33 | .TP 34 | \fBdirmode=\fR\fIDIRMODE 35 | define the permissions for the multilink control directory(see chmod). MODE is an octal number. 36 | If omitted, is computed from mode. 37 | .TP 38 | \fBgrp=\fR\fIGROUP 39 | define the group ownership of the multilink. 40 | .SH EXAMPLES 41 | .B multi:///tmp/multi 42 | .br 43 | Other virtual machines, namespaces or vde_plug can join this multilink using \fBvde:///tmp/hub\fR or simply \fB/tmp/hub\fR 44 | .br 45 | Given two virtual machines using \fBmulti:///tmp/vm1\fR and \fBmulti:///tmp/vm2\fR respectively, it is possible to 46 | connect them using \fBvde_plug /tmp/vm1 /tmp/vm2\fR. If the second virtual machine is running on a remote hosts; 47 | \fBip1.vm2.domain.org\fR and \fBip2.vm2.domain.org\fR are two ip addresses permitting to reach that remote host using 48 | different paths, the command \fBvde_plug /tmp/vm1 = ssh ip1.vm2.domain.org vde_plug /tmp/vm2\fR connects the two vms. 49 | In a second time is possible to run \fBvde_plug /tmp/vm1 = ssh ip2.vm2.domain.org vde_plug /tmp/vm2\fR to create another 50 | channel on the other path. When both connections are in place packets can arrive duplicated (the upper protocols can 51 | manage the problem). Then the process connecting the remotevm using \fBip1.vm2.domain.org\fR can be killed, completing 52 | in this way the (hiccup-less) handoff. 53 | .br 54 | .B multi:///tmp/multi[mode=0666] 55 | .br 56 | It is the same multilink, but everybody is allowed to connect their processes. 57 | .SH NOTICE 58 | Virtual Distributed Ethernet is not related in any way with 59 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 60 | i.e. the German "Association for Electrical, Electronic & Information 61 | Technologies"). 62 | .SH SEE ALSO 63 | \fBvde_plug\fP(1), 64 | -------------------------------------------------------------------------------- /man/libvdeplug_null.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_NULL 1 "April 30, 2017" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_null - network terminator plug 4 | .SH SYNOPSIS 5 | libvdeplug_null.so 6 | .SH DESCRIPTION 7 | This is a libvdeplug module implementing a networking sink/terminator. 8 | 9 | This module of libvdeplug4 can be used in any program supporting vde like 10 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 11 | 12 | The vde_plug_url syntax of this module is the following: 13 | .RS 14 | .B null:// 15 | .br 16 | .RE 17 | 18 | This plug does not generate any networking traffic and all the packets sent to this plug get dropped. 19 | 20 | .SH EXAMPLES 21 | This command creates a switch (without the null plug the command vde_plug adds the stream stdin/stdout 22 | as a node of the switch). 23 | .B vde_plug null:// switch://tmp/myswitch 24 | .br 25 | .SH NOTICE 26 | Virtual Distributed Ethernet is not related in any way with 27 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 28 | i.e. the German "Association for Electrical, Electronic & Information 29 | Technologies"). 30 | .SH SEE ALSO 31 | \fBvde_plug\fP(1), 32 | -------------------------------------------------------------------------------- /man/libvdeplug_ptp.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_PTP 1 "August 23, 2016" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_ptp - vdeplug module for point to point connections 4 | .SH SYNOPSIS 5 | libvdeplug_ptp.so 6 | .SH DESCRIPTION 7 | This module interconnects two vde supporting tools by a point to point 8 | communication line. 9 | This module of libvdeplug4 can be used in any program supporting vde like 10 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 11 | 12 | The vde_plug_url syntax of this module is the following: 13 | .RS 14 | .br 15 | \fBptp://\fIpath_of_the_socket\fR 16 | .RE 17 | 18 | .SH EXAMPLES 19 | .B ptp:///tmp/sock 20 | .br 21 | The same vde_plug_url can be used at both ends of the connection. 22 | The first program creates the socket \fB/tmp/sock\fR. The second program connects to 23 | \fB/tmp/sock\fR, when it discovers that the socket already exists. 24 | .SH NOTICE 25 | Virtual Distributed Ethernet is not related in any way with 26 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 27 | i.e. the German "Association for Electrical, Electronic & Information 28 | Technologies"). 29 | .SH SEE ALSO 30 | \fBvde_plug\fP(1), 31 | -------------------------------------------------------------------------------- /man/libvdeplug_switch.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_SWITCH 1 "April 30, 2017" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_switch - multiplexing vdeplug module: switch 4 | .SH SYNOPSIS 5 | libvdeplug_switch.so 6 | .SH DESCRIPTION 7 | This is a libvdeplug multiplex module implementing a vde switch. 8 | 9 | This module of libvdeplug4 can be used in any program supporting vde like 10 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 11 | 12 | The vde_plug_url syntax of this module is the following: 13 | .RS 14 | \fBswitch://\fR[\fIpath\fR] 15 | .br 16 | \fBswitch://\fR[\fIpath\fR]\fB[\fR[\fIOPTION\fR][\fB/\fIOPTION\fR][\fB/\fIOPTION\fR]...\fB]\fR 17 | .br 18 | .RE 19 | 20 | If \fIpath\fR is omitted the path of the switch is /tmp/vdenode_$USERNAME (e.g. /tmp/vdenode_john 21 | if the username is john). 22 | 23 | This switch supports 801.1Q vlan as a trunk switch, i.e. all the VLAN tagged packets are forwarded as 24 | such. The forwarding table uses a key including both the MAC address and th VLAN id. 25 | 26 | .SH OPTIONS 27 | .TP 28 | \fBhashsize=\fR\fINUM 29 | set the size of the forwarding hash table. (default value 256) 30 | .TP 31 | \fBexpiretime=\fR\fISECONDS 32 | set the expire time of the forwarding table entries. (default value 120) 33 | .TP 34 | \fBhashseed=\fR\fINUM 35 | set a hash seed, in case the hash function generates too many collisions. 36 | .TP 37 | \fBmode=\fR\fIMODE 38 | define the permissions for the switch (see chmod). MODE is an octal number. 39 | The standard permission mask is: 0600 (only processes owning to the same user can join the network). 40 | .TP 41 | \fBdirmode=\fR\fIDIRMODE 42 | define the permissions for the switch control directory(see chmod). MODE is an octal number. 43 | If omitted, is computed from mode. 44 | .TP 45 | \fBgrp=\fR\fIGROUP 46 | define the group ownership of the switch. 47 | .SH EXAMPLES 48 | .B switch:///tmp/switch 49 | .br 50 | Other virtual machines, namespaces or vde_plug can join this switch using \fBvde:///tmp/switch\fR or simply \fB/tmp/switch\fR 51 | .br 52 | .B switch:///tmp/switch[mode=0666/hashsize=1024] 53 | .br 54 | It is the same switch, but everybody is allowed to connect their processes and the hash table has 1024 entries. 55 | .br 56 | The null plug can be used to create a stand-alone vde switch: 57 | .br 58 | .B vde_plug null:// switch:///tmp/myswitch 59 | .br 60 | The following command creates a switch connected to a tap virtual interface 61 | .br 62 | .B vde_plug tap://mytap switch:///tmp/myswitch 63 | 64 | .SH NOTICE 65 | Virtual Distributed Ethernet is not related in any way with 66 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 67 | i.e. the German "Association for Electrical, Electronic & Information 68 | Technologies"). 69 | .SH SEE ALSO 70 | \fBvde_plug\fP(1), 71 | -------------------------------------------------------------------------------- /man/libvdeplug_tap.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_TAP 1 "August 23, 2016" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_tap - vdeplug module: tap interface 4 | .SH SYNOPSIS 5 | libvdeplug_tap.so 6 | .SH DESCRIPTION 7 | This is the standard vdeplug module to connect a TAP interface. 8 | This module of libvdeplug4 can be used in any program supporting vde like 9 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 10 | \fBtunctl\fR or \fBvde_tunctl\fR can be used to preconfigure a TAP device for use by a particular user. 11 | 12 | The vde_plug_url syntax of this module is the following: 13 | .RS 14 | .br 15 | \fBtap://\fIname_of_tap_interface\fR 16 | .RE 17 | 18 | .SH EXAMPLES 19 | .B tap://mytap 20 | .br 21 | This vde_plug_url refers the tap interface named \fBmytap\fR. 22 | .SH NOTICE 23 | Virtual Distributed Ethernet is not related in any way with 24 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 25 | i.e. the German "Association for Electrical, Electronic & Information 26 | Technologies"). 27 | .SH SEE ALSO 28 | \fBvde_plug\fP(1), 29 | \fBtunctl\fP(1), 30 | \fBvde_tunctl\fP(1), 31 | -------------------------------------------------------------------------------- /man/libvdeplug_udp.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_UDP 1 "August 23, 2016" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_udp - vdeplug module for point to point connections using UDP 4 | .SH SYNOPSIS 5 | libvdeplug_udp.so 6 | .SH DESCRIPTION 7 | \fBlibvdeplug_udp\fR creates a point to point connection between two vde supporting 8 | tools using UDP. 9 | This module of libvdeplug4 can be used in any program supporting vde like 10 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 11 | 12 | The network connection created by this module is not encrypted so the data transferred 13 | can be intercepted by network analyzer programs. 14 | 15 | The vde_plug_url syntax of this module is the following: 16 | .RS 17 | .br 18 | \fBudp://\fR"[\fIsrc_address\fB:\fR]\fIsrc_port\fB->\fIdest_address\fB:\fIdest_port\fR" 19 | .RE 20 | 21 | .SH EXAMPLES 22 | .B udp://"2000->host_b.domain_b.org:3000" 23 | .br 24 | .B udp://"3000->host_a.domain_a.org:2000" 25 | .br 26 | These are the vde_plug_urls to use at host_a.domain_a.org and host_b.domain_b.org respectively to 27 | create a connection between port 2000 at host_a and port 3000 at port_b. 28 | 29 | .SH NOTICE 30 | Virtual Distributed Ethernet is not related in any way with 31 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 32 | i.e. the German "Association for Electrical, Electronic & Information 33 | Technologies"). 34 | .SH SEE ALSO 35 | \fBvde_switch\fP(1), 36 | \fBvde_plug\fP(1), 37 | -------------------------------------------------------------------------------- /man/libvdeplug_vde.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_VDE 1 "August 23, 2016" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_vde - vdeplug module for vde_switch based networks 4 | .SH SYNOPSIS 5 | libvdeplug_vde.so 6 | .SH DESCRIPTION 7 | This is the standard vdeplug module for vde_switch based networks. 8 | This module of libvdeplug4 can be used in any program supporting vde like 9 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 10 | The vde_plug_url syntax of the module is the following: 11 | .RS 12 | .br 13 | \fBvde://\fIpath_of_the_switch\fR[\fB[\fIport#_or_portgroup\fB]\fR] 14 | .RE 15 | 16 | This is the default module for libvdeplug, any string not containing '://' (like a path) 17 | is processes by libvdeplug_vde. (e.g. /tmp/vde.ctl is equivalent to vde:///tmp/vde.ctl). 18 | 19 | .SH EXAMPLES 20 | .B vde:///tmp/myswitch 21 | .br 22 | This vde_plug_url refers to the vde_switch identified by the directory \fB/tmp/vde_switch\fR. 23 | Please note that there are three slashes '///' as 'vde://' is the prefix and the third slash is 24 | the first character of the absolute path. 25 | .br 26 | .B vde://thisswitch[3] 27 | .br 28 | this means the port #3 of the switch whose identifier is \fBthisswitch\fR in the current directory 29 | .br 30 | .B vde:///var/run/vde.ctl[privatelan] 31 | .br 32 | this is used to create a connetion to the pertgroup \fBprivatelan\fR of the switch \fB/var/run/vde.ctl\fR. 33 | .SH NOTICE 34 | Virtual Distributed Ethernet is not related in any way with 35 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 36 | i.e. the German "Association for Electrical, Electronic & Information 37 | Technologies"). 38 | .SH SEE ALSO 39 | \fBvde_switch\fP(1), 40 | \fBvde_plug\fP(1), 41 | -------------------------------------------------------------------------------- /man/libvdeplug_vxlan.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_VXLAN 1 "August 23, 2016" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_vxlan - vxlan vdeplug module 4 | .SH SYNOPSIS 5 | libvdeplug_vxlan.so 6 | .SH DESCRIPTION 7 | This is the libvdeplug module to join vxlan networks. 8 | Only one process per host can join each vxlan network. 9 | 10 | This module of libvdeplug4 can be used in any program supporting vde like 11 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 12 | 13 | The vde_plug_url syntax of this module is the following: 14 | .RS 15 | .br 16 | \fBvxlan://\fR[\fImulticast_addr\fR][\fB/\fIOPTION\fR][\fB/\fIOPTION\fR] 17 | .RE 18 | 19 | If \fImulticast_addr\fR is omitted libvdeplug_vxlan uses the default addresses: 20 | \fB239.0.0.1\fR for IPv4 and \fBff05:56de::1\fR for IPv6. 21 | 22 | .SH OPTIONS 23 | .TP 24 | \fBv4\fR 25 | use IPv4 26 | .TP 27 | \fBv6\fR 28 | use IPv6 29 | .TP 30 | \fBport=\fR \fIPORT 31 | define the multicast port (default value 4789) 32 | .TP 33 | \fBvni=\fR \fIVNI 34 | define the virtual network identifier (default value 1) 35 | .TP 36 | \fBttl=\fR \fITTL 37 | define the time-to-live (default value 1). 38 | \fBhashsize=\fR\fIHASHSIZE 39 | set the size of the hash table for packet switching 40 | .TP 41 | \fBexpiretime=\fR\fIEXPIRETIME 42 | set the maximum age in seconds of valid packet switching entries 43 | .TP 44 | \fBif=\fR\fIINTERFACE 45 | set the (real) network interface to use. 46 | 47 | .SH EXAMPLES 48 | .B vxlan://239.0.0.1 49 | .br 50 | This vde_plug_url refers to the vxlan network defined on the multicast address 239.0.0.1, vni=1. 51 | .sp 52 | Programs using 53 | .br 54 | .B vxlan://ff15::3/port=12345/vni=42 55 | .br 56 | join the same vxlan network defined by the multicast address ff15::1, port 12345, vni is 42. 57 | .SH NOTICE 58 | Virtual Distributed Ethernet is not related in any way with 59 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 60 | i.e. the German "Association for Electrical, Electronic & Information 61 | Technologies"). 62 | .SH SEE ALSO 63 | \fBvde_plug\fP(1), 64 | -------------------------------------------------------------------------------- /man/libvdeplug_vxvde.1: -------------------------------------------------------------------------------- 1 | .TH LIBVDEPLUG_VXVDE 1 "August 23, 2016" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | libvdeplug_vxvde - vdeplug module for vde_switch based networks 4 | .SH SYNOPSIS 5 | libvdeplug_vxvde.so 6 | .SH DESCRIPTION 7 | This is the libvdeplug module to join vxvde networks. 8 | Vxvde is a distributed implementation of virtual networks. There is no need for extra processes 9 | like virtual switches. 10 | 11 | This module of libvdeplug4 can be used in any program supporting vde like 12 | \fBvde_plug\fR, \fBkvm\fR, \fBqemu\fR, \fBuser-mode-linux\fR and \fBvirtualbox\fR. 13 | 14 | The vde_plug_url syntax of this module is the following: 15 | .RS 16 | .br 17 | \fBvxvde://\fR[\fImulticast_addr\fR][\fB/\fIOPTION\fR][\fB/\fIOPTION\fR] 18 | .RE 19 | 20 | If \fImulticast_addr\fR is omitted libvdeplug_vxvde uses the default addresses: 21 | \fB239.0.0.1\fR for IPv4 and \fBff05:56de::1\fR for IPv6. 22 | 23 | .SH OPTIONS 24 | .TP 25 | \fBv4\fR 26 | use IPv4 27 | .TP 28 | \fBv6\fR 29 | use IPv6 30 | .TP 31 | \fBport=\fR\fIPORT 32 | define the multicast port (default value 14789) 33 | .TP 34 | \fBvni=\fR\fIVNI 35 | define the virtual network identifier (default value 1). 36 | (a group name can be used as VNI, in that case the vni is the group id). 37 | .TP 38 | \fBttl=\fR\fITTL 39 | define the time-to-live (default value 1). 40 | .TP 41 | \fBgrp=\fR\fIgroup_name_or_number 42 | Set the VNI and the last three bytes of the IP address to the group id. 43 | .TP 44 | \fBhashsize=\fR\fIHASHSIZE 45 | set the size of the hash table for packet switching 46 | .TP 47 | \fBexpiretime=\fR\fIEXPIRETIME 48 | set the maximum age in seconds of valid packet switching entries 49 | .TP 50 | \fBif=\fR\fIINTERFACE 51 | set the (real) network interface to use. 52 | .SH EXAMPLES 53 | .B vxvde://239.0.0.1 54 | .br 55 | This vde_plug_url refers to the vxvde network defined on the multicast address 239.0.0.1, vni=1. 56 | .sp 57 | Programs using 58 | .br 59 | .B vxvde://ff15::3/port=12345/vni=42 60 | .br 61 | join the same vxvde network defined by the multicast address ff15::1, port 12345, vni is 42. 62 | .SH NOTICE 63 | Virtual Distributed Ethernet is not related in any way with 64 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 65 | i.e. the German "Association for Electrical, Electronic & Information 66 | Technologies"). 67 | .SH SEE ALSO 68 | \fBvde_plug\fP(1), 69 | -------------------------------------------------------------------------------- /man/vde_close.3: -------------------------------------------------------------------------------- 1 | libvdeplug.3 -------------------------------------------------------------------------------- /man/vde_ctlfd.3: -------------------------------------------------------------------------------- 1 | libvdeplug.3 -------------------------------------------------------------------------------- /man/vde_datafd.3: -------------------------------------------------------------------------------- 1 | libvdeplug.3 -------------------------------------------------------------------------------- /man/vde_open.3: -------------------------------------------------------------------------------- 1 | libvdeplug.3 -------------------------------------------------------------------------------- /man/vde_plug.1: -------------------------------------------------------------------------------- 1 | .TH VDE_PLUG 1 "August 23, 2016" "Virtual Distributed Ethernet" 2 | .SH NAME 3 | vde_plug \- Virtual Distributed Ethernet plug (two plugs creates a vde cable) 4 | .SH SYNOPSIS 5 | .B vde_plug 6 | [ 7 | .I OPTIONS 8 | ] 9 | [ 10 | .I VNL 11 | ] 12 | .br 13 | .B vde_plug 14 | [ 15 | .I OPTIONS 16 | ] 17 | .I VNL 18 | .I VNL 19 | .br 20 | .B vde_plug 21 | [ 22 | .I OPTIONS 23 | ] 24 | .B = 25 | .I command 26 | [ 27 | .I args 28 | ] 29 | .br 30 | .B vde_plug 31 | [ 32 | .I OPTIONS 33 | ] 34 | .I VNL 35 | .B = 36 | .I command 37 | [ 38 | .I args 39 | ] 40 | .br 41 | .SH DESCRIPTION 42 | A 43 | \fBvde_plug\fR 44 | is a plug to be connected into a VDE network. 45 | 46 | VDE network sockets are named using the Virtual Network Locator (VNL) 47 | syntax, i.e. \fImodule\fB://\fIspecific_address\fR. 48 | e.g. \fBvde:///home/user/myswitch\fR or \fBvxvde://239.0.0.1\fR. 49 | The default module is \fBlibvdeplug_vde(1)\fR (connection to a \fBvde_switch(1)\fR) 50 | and can be omitted. e.g. \fB/home/user/myswitch\fR means 51 | \fBvde:///home/user/myswitch\fR 52 | 53 | \fBvde_plug\fR can have zero, one or two VNL arguments. 54 | In case of zero or one argument the network communication is converted in 55 | a byte stream. Packets from the VDE network are sent to stdout and bytes 56 | from stdin are converted into packets and injected in the VDE network. 57 | When a VNL is omitted or it is an empty argument 58 | (\fB''\fR) \fBvde_plug\fR tries to connect to a 59 | default network (defined by the user in \fB$HOME/.vde2/default.switch\fR 60 | otherwise \fBvde:///run/vde.ctl\fR or \fBvde:///tmp/vde.ctl\fR). 61 | 62 | This tool has been designed to be used together with 63 | .B dpipe (1) 64 | to interconnect a second vde_plug to another switch, working as a 65 | virtual ethernet crossed cable between the two switches. 66 | 67 | The command 68 | .RS 69 | .br 70 | .B dpipe vde_plug = vde_plug vde:///tmp/vde2.ctl 71 | .RE 72 | connects two local switches: the former is using the standard control socket /tmp/vde.ctl 73 | (or /var/run/vde.ctl) while the latter is using /tmp/vde2.ctl. 74 | 75 | \fBvde_plug\fR creates a virtual cable between to VDE networks 76 | when two VNL arguments are present in the command line. 77 | The previous command is equivalent to: 78 | .RS 79 | .br 80 | .B vde_plug /tmp/vde.ctl /tmp/vde2.ctl 81 | .RE 82 | 83 | The following example connects a vxvde network to a tap interfave 84 | .RS 85 | .br 86 | .B vde_plug vxvde://239.1.2.3 tap://mytap 87 | .RE 88 | 89 | The command 90 | .RS 91 | .br 92 | .B dpipe vde_plug = ssh remote.machine.org vde_plug 93 | .RE 94 | connects two remote switches. 95 | If for example the two vde_switches run as daemon and they are connected to tap interfaces 96 | a level 2 encrypted tunnel is established. 97 | 98 | While \fBdpipe\fR supports more complex vitrual network structures (e.g. including \fBwirefilter(1)\fR to 99 | emulate network conditions) \fBvde_plug\fR has been designed to provide simple syntax options 100 | to implement the most common virtual network scenarios. 101 | It is possible to use an equal sign (\fB=\fR) followed by a command and its optional 102 | arguments in place of the second VNL. 103 | In this case the packets from/to the network are converted into a bidirectional byte stream 104 | provided as stdin and stdout to the command. 105 | The previous command have the same effect of: 106 | .RS 107 | .br 108 | .B vde_plug = ssh remote.machine.org vde_plug 109 | .RE 110 | (the first VNL is omitted). 111 | 112 | This example: 113 | .RS 114 | .br 115 | .B vde_plug vxvde://239.1.2.3 = ssh vde_plug tap://remotetap 116 | .RE 117 | connects a vxvde network to a tap interface of a remote host. 118 | 119 | vde_plug can also be established as a login shell for users. 120 | The following command works as in the previous example 121 | .RS 122 | .br 123 | .B vde_plug = ssh vdeuser@remote.machine.org vde_plug 124 | .RE 125 | where vdeuser is the user with vde_plug as standard shell. 126 | All the remote accesses are logged by syslog at the beginning and at the 127 | end of each session and the IP address used are logged if \fBvdeuser\fR belongs 128 | to the \fBvdeplug_iplog\fR group. 129 | Attempts to login without the command vde_plug at the end or to 130 | run on the remote host other commands but vde_plug 131 | are blocked and the violation is logged by syslog. 132 | 133 | .SH OPTIONS 134 | .TP 135 | \fB\-d 136 | .TQ 137 | \fB\-\-daemon 138 | run as a daemon. 139 | .TP 140 | \fB\-p\fR \fIPIDFILE 141 | .TQ 142 | \fB\-\-pidfile\fR \fIPIDFILE 143 | write the process id to the file \fIPIDFILE\fR 144 | .TP 145 | \fB\-l 146 | .TQ 147 | \fB\-\-log 148 | log START/STOP of vde_plug on syslog 149 | .TP 150 | \fB\-L 151 | .TQ 152 | \fB\-\-iplog 153 | log START/STOP of vde_plug and the IP addresses of hosts seen on the stream 154 | (or on the second VNL) on syslog. 155 | .TP 156 | \fB\-\-port "\fIportnum\fP" 157 | Obsolete option, use the syntax of the libvdeplug_vde module instead, 158 | add the port number in square brackets suffix (e.g. \fBvde://tmp/myswitch[10]\fR). 159 | It is possible to decide which port of the switch to use. 160 | When this option is not specified the switch assigns the first 161 | available unused port (if any). 162 | It is possible to connect several cables in the same switch port: 163 | in this way all this cables work concurrently. 164 | It means that packet can result as duplicate but no ARP table loops are 165 | generated. 166 | Is useful when vde is used for mobility. Several physical interfaces can 167 | be used at a time during handoffs to prevent hichups in connectivity. 168 | log START/STOP of vde_plug on syslog 169 | .TP 170 | \fB\-g \fIgroup 171 | .TQ 172 | \fB\-\-group \fIgroup 173 | group ownership of the communication socket. For security when more 174 | want to share a switch it is better to use a unix group to own the comm sockets 175 | so that the network traffic cannot be sniffed. 176 | .TP 177 | \fB\-m \fIoctal-mode\fR 178 | .TQ 179 | \fB\-\-mod \fIoctal-mode\fR 180 | octal chmod like permissions for the comm sockets 181 | .TP 182 | \fB\-G \-M 183 | .TQ 184 | \fB\-\-port2 \-\-group2 \-\-mod2 185 | These options, valid in the syntax with two VNLs, have the the same meaning of \-p \-g \-m. 186 | The uppercase options or the long options with a trailing 2 refer to the second VNL. 187 | .TP 188 | \fB\-D\fR \fIDESCR 189 | .TQ 190 | \fB\-\-descr\fR \fIDESCR 191 | set the description of this connection to \fIDESCR\fR (e.g. port/print command on a 192 | vde_switch shows this description). 193 | 194 | 195 | .SH NOTICE 196 | Virtual Distributed Ethernet is not related in any way with 197 | www.vde.com ("Verband der Elektrotechnik, Elektronik und Informationstechnik" 198 | i.e. the German "Association for Electrical, Electronic & Information 199 | Technologies"). 200 | 201 | .SH SEE ALSO 202 | \fBvde_switch\fP(1), 203 | \fBvdeq\fP(1), 204 | \fBdpipe\fP(1), 205 | \fBlibvdeplug_p2p.1\fR, 206 | \fBlibvdeplug_udp.1\fR, 207 | \fBlibvdeplug_vxlan.1\fR, 208 | \fBlibvdeplug_tap.1\fR, 209 | \fBlibvdeplug_vde.1\fR, 210 | \fBlibvdeplug_vxvde.1\fR. 211 | .br 212 | .SH AUTHOR 213 | VDE is a project by Renzo Davoli 214 | -------------------------------------------------------------------------------- /man/vde_recv.3: -------------------------------------------------------------------------------- 1 | libvdeplug.3 -------------------------------------------------------------------------------- /man/vde_send.3: -------------------------------------------------------------------------------- 1 | libvdeplug.3 -------------------------------------------------------------------------------- /srcvdeplug4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | add_executable( 4 | vde_plug vde_plug.c vde_plug_log.c vde_plug_iplog.c openclosepidfile.c 5 | selfsighandler.c 6 | ) 7 | target_link_libraries(vde_plug vdeplug) 8 | 9 | add_executable(dpipe dpipe.c openclosepidfile.c selfsighandler.c) 10 | 11 | install( 12 | TARGETS vde_plug dpipe 13 | RUNTIME 14 | DESTINATION ${CMAKE_INSTALL_BINDIR} 15 | ) 16 | 17 | -------------------------------------------------------------------------------- /srcvdeplug4/dpipe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2003-2016 Renzo Davoli, University of Bologna 3 | * 4 | * dpipe: dual pipe 5 | * 6 | * VDE is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 2 9 | * of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; If not, see . 18 | * 19 | */ 20 | 21 | #define _GNU_SOURCE 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | #define DAEMONIZE 0x1 36 | #define NO_WRAPPROC 0x2 37 | #define CLEANUP_NEEDED 0x4 38 | #define NO_CLEANUP 0x8 39 | 40 | #if 0 41 | /* debug */ 42 | #define execvp(X,Y) \ 43 | ({ char **y; \ 44 | fprintf(stderr,"execvp \"%s\" -",(X)); \ 45 | for (y=(Y); *y != NULL; y++) \ 46 | fprintf(stderr,"\"%s\"",*y); \ 47 | fprintf(stderr,"\n"); \ 48 | sleep (10); \ 49 | }) 50 | #endif 51 | 52 | static char *progname; 53 | pid_t lastpid = -1; 54 | 55 | static void cleanup(void) 56 | { 57 | openclosepidfile(NULL); 58 | openclosepgrpfile(NULL); 59 | } 60 | 61 | static void sigcleanup(void) 62 | { 63 | cleanup(); 64 | if (lastpid >= 0) 65 | kill(lastpid,SIGTERM); 66 | } 67 | 68 | int waitfortermination(pid_t last) { 69 | int status; 70 | int rval = -1; 71 | pid_t pid; 72 | lastpid = last; 73 | while ((pid = waitpid(-1, &status, 0)) >= 0) { 74 | if (pid == last) 75 | rval = WEXITSTATUS(status); 76 | } 77 | return rval; 78 | } 79 | 80 | 81 | /* return the index of the next '=' (maybe with { } before or after) 82 | if there is { or } before =, this must match dirchar i.e. the 83 | symbol following the previous = 84 | dirchar is updated for the next split. */ 85 | int splitindex(int argc, char *argv[], int *dirchar) 86 | { 87 | register int i; 88 | 89 | for (i=0; i= argc) { 149 | pid_t last; 150 | if (newdirchar != 0) 151 | usage_and_exit(); 152 | if (flags & NO_WRAPPROC) { 153 | if ((flags & CLEANUP_NEEDED) && fork() == 0) { 154 | pid_t ppid = getppid(); 155 | close(STDIN_FILENO); 156 | close(STDOUT_FILENO); 157 | while (1) { 158 | if (kill(ppid,0) < 0) 159 | break; 160 | sleep(1); 161 | } 162 | exit(0); 163 | } else { 164 | execvp(argv[0],argv); 165 | exit(127); 166 | } 167 | } else { 168 | if ((last = fork()) == 0) { 169 | execvp(argv[0],argv); 170 | exit(127); 171 | } else { 172 | close(STDIN_FILENO); 173 | close(STDOUT_FILENO); 174 | return last; 175 | } 176 | } 177 | } else { 178 | /* the chain has more than one elements. */ 179 | char **argv1,**argv2; 180 | int p1[2],p2[2]; 181 | 182 | if (argc < 3 || split == 0 || split == argc-1) 183 | usage_and_exit(); 184 | 185 | if (pipe(p1) < 0) { 186 | perror("pipe"); 187 | exit(1); 188 | } 189 | 190 | /* ..chain already processed.. = this =.... 191 | two pipes needed */ 192 | if (olddirchar == 0) { 193 | if (pipe(p2) < 0) { 194 | perror("second pipe"); 195 | exit(1); 196 | } 197 | } 198 | 199 | argv[split]=NULL; 200 | argv1=argv; 201 | argv2=argv+(split+1); 202 | 203 | if (fork() == 0) { 204 | /* child prepare to run the program */ 205 | switch (olddirchar) { 206 | case 0: 207 | /* ... = this = ... */ 208 | close(p1[1]); close(p2[0]); 209 | if (p1[0] != alternate_stdin){ 210 | dup2(p1[0],alternate_stdin); 211 | close(p1[0]); 212 | } 213 | if (p2[1] != alternate_stdout){ 214 | dup2(p2[1],alternate_stdout); 215 | close(p2[1]); 216 | } 217 | break; 218 | case '{': 219 | /* ... ={ this {= ... */ 220 | close(p1[1]); 221 | dup2(p1[0],STDIN_FILENO); 222 | close(p1[0]); 223 | break; 224 | case '}': 225 | /* ... =} this }= ... */ 226 | close(p1[0]); 227 | dup2(p1[1],STDOUT_FILENO); 228 | close(p1[1]); 229 | break; 230 | default: 231 | fprintf(stderr,"Error\n"); 232 | } 233 | execvp(argv1[0],argv1); 234 | exit(127); 235 | } else { 236 | /* parent rename the pipes as STDIN_FILENO and STDOUT_FILENO 237 | and process the remaining part of the chain */ 238 | switch (olddirchar) { 239 | case 0: 240 | /* ... = this = ... */ 241 | close(p2[1]); close(p1[0]); 242 | dup2(p2[0],STDIN_FILENO); 243 | dup2(p1[1],STDOUT_FILENO); 244 | close(p2[0]); close(p1[1]); 245 | break; 246 | case '{': 247 | /* ... ={ this {= ... */ 248 | close(p1[0]); 249 | dup2(p1[1],STDOUT_FILENO); 250 | close(p1[1]); 251 | break; 252 | case '}': 253 | /* ... =} this }= ... */ 254 | close(p1[1]); 255 | dup2(p1[0],STDIN_FILENO); 256 | close(p1[0]); 257 | break; 258 | default: 259 | fprintf(stderr,"Error\n"); 260 | } 261 | return rec_dpipe(argc-split-1,argv2,newdirchar,flags); 262 | } 263 | } 264 | return 0; 265 | } 266 | 267 | /* start the first process of the dpipe chain */ 268 | pid_t start_dpipe(int argc, char *argv[], unsigned int flags) 269 | { 270 | int split; 271 | char **argv1,**argv2; 272 | int p1[2],p2[2]; 273 | int dirchar=0; 274 | 275 | alternate_fd(); 276 | split=splitindex(argc,argv,&dirchar); 277 | 278 | if (argc < 3 || split == 0 || split >= argc-1) 279 | usage_and_exit(); 280 | 281 | if (pipe(p1) < 0 || pipe(p2) < 0) { 282 | perror("pipe"); 283 | exit(1); 284 | } 285 | 286 | argv[split]=NULL; 287 | argv1=argv; 288 | argv2=argv+(split+1); 289 | 290 | if (fork() == 0) { 291 | close(p1[1]); close(p2[0]); 292 | dup2(p1[0],STDIN_FILENO); 293 | dup2(p2[1],STDOUT_FILENO); 294 | close(p1[0]); close(p2[1]); 295 | execvp(argv1[0],argv1); 296 | exit(127); 297 | } else { 298 | close(p2[1]); close(p1[0]); 299 | dup2(p2[0],STDIN_FILENO); 300 | dup2(p1[1],STDOUT_FILENO); 301 | close(p1[1]); close(p2[0]); 302 | return rec_dpipe(argc-split-1,argv2,dirchar,flags); 303 | } 304 | } 305 | 306 | char *short_options = "+dp:P:hnN"; 307 | struct option long_options[] = { 308 | {"nowrapproc", no_argument, 0, 'n' }, 309 | {"nowrapnoclean", no_argument, 0, 'N' }, 310 | {"pidfile", required_argument, 0, 'p' }, 311 | {"pgrpfile", required_argument, 0, 'P' }, 312 | {"daemon", no_argument, 0, 'd' }, 313 | {"help", no_argument, 0, 'h' }, 314 | {0, 0, 0, 0} 315 | }; 316 | 317 | int main(int argc, char *argv[]) 318 | { 319 | unsigned int flags = 0; 320 | char *pidfile = NULL; 321 | char *pgrpfile = NULL; 322 | int rval; 323 | 324 | progname = argv[0]; 325 | 326 | while (1) { 327 | int option_index = 0; 328 | int c; 329 | c = getopt_long(argc, argv, short_options, 330 | long_options, &option_index); 331 | if (c == -1) break; 332 | switch (c) { 333 | case 'p' : pidfile = optarg; 334 | flags |= CLEANUP_NEEDED; 335 | break; 336 | case 'P' : pgrpfile = optarg; 337 | flags |= CLEANUP_NEEDED; 338 | break; 339 | case 'd' : flags |= DAEMONIZE; 340 | break; 341 | case 'n' : flags |= NO_WRAPPROC; 342 | break; 343 | case 'N' : flags |= NO_WRAPPROC | NO_CLEANUP; 344 | break; 345 | case 'h' : usage_and_exit(); 346 | } 347 | } 348 | 349 | if (flags & NO_CLEANUP) 350 | flags &= ~CLEANUP_NEEDED; 351 | argc -= optind; 352 | argv += optind; 353 | 354 | if ((flags & DAEMONIZE) != 0) { 355 | if (daemon(0,0) < 0) { 356 | fprintf(stderr,"%s daemonize: %s\n", progname, strerror(errno)); 357 | exit(1); 358 | } 359 | } else if (setpgrp() != 0) { 360 | fprintf(stderr,"Err: cannot create pgrp\n"); 361 | exit(1); 362 | } 363 | 364 | atexit(cleanup); 365 | setsighandlers(sigcleanup); 366 | 367 | if (pidfile != NULL) 368 | openclosepidfile(pidfile); 369 | if (pgrpfile != NULL) 370 | openclosepgrpfile(pgrpfile); 371 | 372 | rval = waitfortermination(start_dpipe(argc, argv, flags)); 373 | 374 | return rval; 375 | } 376 | -------------------------------------------------------------------------------- /srcvdeplug4/openclosepidfile.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Renzo Davoli, University of Bologna 3 | * 4 | * openclosepidfile 5 | * 6 | * VDE is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 2 9 | * of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; If not, see . 18 | * 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | void openclosepidfile(char *pidfile) { 26 | static char *savepidfile; 27 | if (pidfile != NULL) { 28 | FILE *f = fopen(pidfile,"w"); 29 | if (f != NULL) { 30 | savepidfile = pidfile; 31 | fprintf(f,"%d\n", getpid()); 32 | fclose(f); 33 | } 34 | } else if (savepidfile != NULL) 35 | unlink(savepidfile); 36 | } 37 | 38 | void openclosepgrpfile(char *pidfile) { 39 | static char *savepidfile; 40 | if (pidfile != NULL) { 41 | FILE *f = fopen(pidfile,"w"); 42 | if (f != NULL) { 43 | savepidfile = pidfile; 44 | fprintf(f,"-%d\n", getpgrp()); 45 | fclose(f); 46 | } 47 | } else if (savepidfile != NULL) 48 | unlink(savepidfile); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /srcvdeplug4/openclosepidfile.h: -------------------------------------------------------------------------------- 1 | #ifndef OPENCLOSEPIDFILE_H 2 | #define OPENCLOSEPIDFILE_H 3 | 4 | void openclosepidfile(char *pidfile); 5 | 6 | void openclosepgrpfile(char *pidfile); 7 | 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /srcvdeplug4/selfsighandler.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2003-2016 Renzo Davoli, Ludovico Gardenghi. University of Bologna 3 | * 4 | * signal handler 5 | * 6 | * VDE is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 2 9 | * of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; If not, see . 18 | * 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | static void (*cleanupcopy)(void); 28 | 29 | static void sig_handler(int sig) 30 | { 31 | cleanupcopy(); 32 | signal(sig, SIG_DFL); 33 | if (sig == SIGTERM) 34 | _exit(0); 35 | else 36 | kill(-getpgrp(), sig); 37 | } 38 | 39 | void setsighandlers(void (*cleanup)(void)) 40 | { 41 | /* setting signal handlers. 42 | * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply 43 | * ignores all the others signals which could cause termination. */ 44 | struct { int sig; const char *name; int ignore; } signals[] = { 45 | { SIGHUP, "SIGHUP", 0 }, 46 | { SIGINT, "SIGINT", 0 }, 47 | { SIGPIPE, "SIGPIPE", 1 }, 48 | { SIGALRM, "SIGALRM", 1 }, 49 | { SIGTERM, "SIGTERM", 0 }, 50 | { SIGUSR1, "SIGUSR1", 1 }, 51 | { SIGUSR2, "SIGUSR2", 1 }, 52 | { SIGPROF, "SIGPROF", 1 }, 53 | { SIGVTALRM, "SIGVTALRM", 1 }, 54 | #ifdef SIGPOLL 55 | { SIGPOLL, "SIGPOLL", 1 }, 56 | #ifdef SIGSTKFLT 57 | { SIGSTKFLT, "SIGSTKFLT", 1 }, 58 | #endif 59 | { SIGIO, "SIGIO", 1 }, 60 | { SIGPWR, "SIGPWR", 1 }, 61 | #ifdef SIGUNUSED 62 | { SIGUNUSED, "SIGUNUSED", 1 }, 63 | #endif 64 | #endif 65 | #ifdef VDE_DARWIN 66 | { SIGXCPU, "SIGXCPU", 1 }, 67 | { SIGXFSZ, "SIGXFSZ", 1 }, 68 | #endif 69 | { 0, NULL, 0 } 70 | }; 71 | 72 | int i; 73 | struct sigaction sa = { 74 | .sa_handler = sig_handler, 75 | .sa_flags = 0}; 76 | sigfillset(&sa.sa_mask); 77 | for(i = 0; signals[i].sig != 0; i++) 78 | if (!signals[i].ignore) 79 | if (sigaction(signals[i].sig, &sa, NULL) < 0) 80 | perror("Setting handler"); 81 | for(i = 0; signals[i].sig != 0; i++) 82 | if (signals[i].ignore) 83 | if (signal(signals[i].sig, SIG_IGN) == SIG_ERR) 84 | perror("Setting handler"); 85 | 86 | cleanupcopy = cleanup; 87 | } 88 | -------------------------------------------------------------------------------- /srcvdeplug4/selfsighandler.h: -------------------------------------------------------------------------------- 1 | #ifndef SELFSIGHANDLER_H 2 | #define SELFSIGHANDLER_H 3 | 4 | void setsighandlers(void (*cleanup)(void)); 5 | 6 | #endif //SELFSIGHANDLER_H 7 | -------------------------------------------------------------------------------- /srcvdeplug4/vde_plug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002-2016 Renzo Davoli, University of Bologna 3 | * Modified by Ludovico Gardenghi 2005 4 | * 5 | * vde_plug: connect vde network together 6 | * 7 | * VDE is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; If not, see . 19 | * 20 | */ 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #define VDE_IP_LOG_GROUP "vdeplug_iplog" 50 | #define DEFAULT_DESCRIPTION "vdeplug:" 51 | 52 | int vde_ip_log; 53 | 54 | VDECONN *conn; 55 | VDECONN *conn2; 56 | VDESTREAM *vdestream; 57 | 58 | #define ETH_ALEN 6 59 | #define ETH_HDRLEN (ETH_ALEN+ETH_ALEN+2) 60 | 61 | struct utsname me; 62 | #define myname me.nodename 63 | 64 | void vdeplug_err(void *opaque, int type, char *format,...) 65 | { 66 | va_list args; 67 | 68 | if (isatty(STDERR_FILENO)) { 69 | fprintf(stderr, "%s: Packet length error ",myname); 70 | va_start(args, format); 71 | vfprintf(stderr, format, args); 72 | va_end(args); 73 | fprintf(stderr,"\n"); 74 | } 75 | } 76 | 77 | ssize_t vdeplug_recv(void *opaque, void *buf, size_t count) 78 | { 79 | VDECONN *conn=opaque; 80 | if (__builtin_expect(vde_ip_log != 0, 0)) 81 | vde_ip_check(buf,count); 82 | return vde_send(conn,(char *)buf,count,0); 83 | } 84 | 85 | 86 | int checkuidgroup(uid_t uid, const char *group) { 87 | struct passwd *pw=getpwuid(uid); 88 | int ngroups=0; 89 | if (pw == NULL) return -1; 90 | if (getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ngroups) < 0) { 91 | gid_t gids[ngroups]; 92 | if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngroups) == ngroups) { 93 | struct group *grp; 94 | int i; 95 | while ((grp=getgrent()) != NULL) { 96 | for (i=0; igr_gid == gids[i] && strcmp(grp->gr_name,group) == 0) { 98 | endgrent(); 99 | return 1; 100 | } 101 | } 102 | } 103 | endgrent(); 104 | return 0; 105 | } 106 | } 107 | return -1; 108 | } 109 | 110 | static void cleanup(void) 111 | { 112 | vde_close(conn); 113 | if (conn2 != NULL) vde_close(conn2); 114 | if (vdestream != NULL) vdestream_close(vdestream); 115 | openclosepidfile(NULL); 116 | } 117 | 118 | unsigned char bufin[VDE_ETHBUFSIZE]; 119 | 120 | int plug2stream(void) { 121 | register ssize_t nx; 122 | struct pollfd pollv[] = { 123 | {STDIN_FILENO, POLLIN|POLLHUP}, 124 | {vde_datafd(conn), POLLIN|POLLHUP}, 125 | {vde_ctlfd(conn), POLLIN|POLLHUP}, 126 | }; 127 | 128 | vdestream = vdestream_open(conn,STDOUT_FILENO,vdeplug_recv,vdeplug_err); 129 | 130 | for(;;) { 131 | poll(pollv,3,-1); 132 | if (__builtin_expect(((pollv[0].revents | pollv[1].revents | pollv[2].revents) & POLLHUP || 133 | pollv[2].revents & POLLIN),0)) 134 | break; 135 | if (pollv[0].revents & POLLIN) { 136 | nx = read(STDIN_FILENO,bufin,sizeof(bufin)); 137 | /* if POLLIN but not data it means that the stream has been 138 | * closed at the other end */ 139 | /*fprintf(stderr,"%s: RECV %d %x %x \n",myname,nx,bufin[0],bufin[1]);*/ 140 | if (nx == 0) 141 | break; 142 | vdestream_recv(vdestream, bufin, nx); 143 | } 144 | if (pollv[1].revents & POLLIN) { 145 | nx = vde_recv(conn,bufin,VDE_ETHBUFSIZE,0); 146 | if (__builtin_expect((nx >= ETH_HDRLEN),1)) 147 | { 148 | vdestream_send(vdestream, bufin, nx); 149 | /*fprintf(stderr,"%s: SENT %d %x %x \n",myname,nx,bufin[0],bufin[1]);*/ 150 | } else if (nx<0) 151 | perror("vde_plug: recvfrom "); 152 | } 153 | } 154 | return(0); 155 | } 156 | 157 | int plug2cmd(char **argv) { 158 | int p2c[2],c2p[2]; 159 | pid_t pid; 160 | if (pipe(p2c) < 0 || pipe(c2p) < 0) { 161 | perror("pipe open"); 162 | return(1); 163 | } 164 | 165 | pid=fork(); 166 | if (pid < 0) { 167 | perror("fork"); 168 | exit(1); 169 | } else if (pid == 0) { 170 | dup2(p2c[0], STDIN_FILENO); 171 | dup2(c2p[1], STDOUT_FILENO); 172 | close(p2c[0]); close(p2c[1]); 173 | close(c2p[0]); close(c2p[1]); 174 | execvp(*argv, argv); 175 | exit(1); 176 | } 177 | dup2(c2p[0], STDIN_FILENO); 178 | dup2(p2c[1], STDOUT_FILENO); 179 | close(p2c[0]); close(p2c[1]); 180 | close(c2p[0]); close(c2p[1]); 181 | 182 | return plug2stream(); 183 | } 184 | 185 | int plug2plug(void) 186 | { 187 | register ssize_t nx; 188 | struct pollfd pollv[] = { 189 | {vde_datafd(conn), POLLIN|POLLHUP}, 190 | {vde_datafd(conn2), POLLIN|POLLHUP}, 191 | {vde_ctlfd(conn), POLLIN|POLLHUP}, 192 | {vde_ctlfd(conn2), POLLIN|POLLHUP} 193 | }; 194 | 195 | for(;;) { 196 | poll(pollv,4,-1); 197 | if ((pollv[0].revents | pollv[1].revents | pollv[2].revents | pollv[2].revents) & POLLHUP || 198 | (pollv[2].revents | pollv[3].revents) & POLLIN) 199 | break; 200 | if (pollv[0].revents & POLLIN) { 201 | nx = vde_recv(conn, bufin, VDE_ETHBUFSIZE,0); 202 | if (__builtin_expect((nx >= ETH_HDRLEN),1)) { 203 | vde_send(conn2, bufin, nx, 0); 204 | /*fprintf(stderr,"0->1 %d ",nx);*/ 205 | } else if (nx<0) 206 | break; 207 | } 208 | if (pollv[1].revents & POLLIN) { 209 | nx = vde_recv(conn2,bufin,VDE_ETHBUFSIZE,0); 210 | if (__builtin_expect((nx >= ETH_HDRLEN),1)) { 211 | vde_send(conn, bufin, nx, 0); 212 | /*fprintf(stderr,"1->0 %d ",nx);*/ 213 | } else if (nx<0) 214 | break; 215 | } 216 | } 217 | return(0); 218 | } 219 | 220 | 221 | static void netusage_and_exit() { 222 | vdeplug_openlog("FAILED"); 223 | fprintf (stderr,"This is a Virtual Distributed Ethernet (vde) tunnel broker. \n" 224 | "This is not a login shell, only vde_plug can be executed\n"); 225 | exit(-1); 226 | } 227 | 228 | static void usage_and_exit(char *progname) { 229 | fprintf (stderr,"Usage:\n" 230 | " %s [ OPTIONS ] \n" 231 | " %s [ OPTIONS ] vde_plug_url\n" 232 | " %s [ OPTIONS ] vde_plug_url vde_plug_url\n" 233 | " %s [ OPTIONS ] = command [args ...]\n" 234 | " %s [ OPTIONS ] vde_plug_url = command [args ...]\n" 235 | " an omitted or empty '' vde_plug_url refer to the default vde service\n" 236 | " i.e. what defined in \"~/.vde2/default.switch\" or\n" 237 | " a standard switch defined by libvdeplug_vde.so (e.g. /var/run/vde.ctl)\n" 238 | "Options:\n" 239 | " -d | --daemon: daemonize the program\n" 240 | " -p PIDFILE | --pidfile PIDFILE: \n" 241 | " write pid of daemon to PIDFILE\n" 242 | " -l | --log: log START/STOP of vde_plug on syslog\n" 243 | " -L | --iplog: -l plus log the IP addresses used\n" 244 | " -h | --help: show this short summary\n" 245 | " -g GROUP | --group GROUP: set the group ownership (for vde://...)\n" 246 | " -G GROUP | --group2 GROUP: like -g, for the second plug\n" 247 | " -m MODE | --mod MODE: comm socket protection mode (see chmod) (for vde://...)\n" 248 | " -M MODE | --mod2 MODE: like -m, for the second plug\n" 249 | " --port PORT1, --port2 PORT2:\n" 250 | " obsolete options, set the vde switch port,\n" 251 | " use [port] suffix in the vde_plug_url instead\n" 252 | " -D DESCR | --descr DESCR set the description of this connection to DESCR\n" 253 | " (the default value is \"" DEFAULT_DESCRIPTION "\"\n" 254 | "\n",progname,progname,progname,progname,progname); 255 | exit(-1); 256 | } 257 | 258 | char short_options[] = "c:hp:dm:M:g:G:lLD:"; 259 | struct option long_options[] = { 260 | {"pidfile", required_argument, 0, 'p' }, 261 | {"daemon", no_argument, 0, 'd' }, 262 | {"port", required_argument, 0, 0x100 + 'p'}, 263 | {"port2", required_argument, 0, 0x100 + 'P'}, 264 | {"mod", required_argument, 0, 'm'}, 265 | {"mod2", required_argument, 0, 'M'}, 266 | {"group", required_argument, 0, 'g'}, 267 | {"group2", required_argument, 0, 'G'}, 268 | {"descr", required_argument, 0, 'D' }, 269 | {"log", no_argument, 0, 'l' }, 270 | {"iplog", no_argument, 0, 'L' }, 271 | {"help", no_argument, 0, 'h' }, 272 | {0, 0, 0, 0} 273 | }; 274 | 275 | #include 276 | int main(int argc, char *argv[]) 277 | { 278 | char *progname = basename(argv[0]); 279 | static char *vde_url = NULL; 280 | static char *vde_url2 = NULL; 281 | static char **cmdargv = NULL; 282 | struct vde_open_args open_args = {.port = 0,.group = NULL,.mode = 0700}; 283 | struct vde_open_args open_args2 = {.port = 0,.group = NULL,.mode = 0700}; 284 | int daemonize = 0; 285 | char *pidfile = NULL; 286 | char *description = DEFAULT_DESCRIPTION; 287 | 288 | uname(&me); 289 | 290 | if (argv[0][0] == '-') 291 | netusage_and_exit(); //implies exit 292 | /* option parsing */ 293 | while (1) { 294 | int option_index = 0; 295 | int c; 296 | 297 | c = getopt_long(argc, argv, short_options, long_options, &option_index); 298 | if (c == -1) break; 299 | 300 | switch (c) { 301 | case 'c': 302 | if (strcmp(optarg,"vde_plug") == 0) { 303 | vdeplug_openlog(NULL); 304 | atexit(vdeplug_closelog); 305 | if (checkuidgroup(getuid(), VDE_IP_LOG_GROUP) == 1) 306 | vde_ip_log = 1; 307 | } 308 | else 309 | netusage_and_exit(); //implies exit 310 | break; 311 | 312 | case 0x100 + 'p': 313 | open_args.port = atoi(optarg); 314 | if (open_args.port <= 0) 315 | usage_and_exit(progname); //implies exit 316 | break; 317 | 318 | case 0x100 + 'P': 319 | open_args2.port = atoi(optarg); 320 | if (open_args2.port <= 0) 321 | usage_and_exit(progname); //implies exit 322 | break; 323 | 324 | case 'h': 325 | usage_and_exit(progname); //implies exit 326 | break; 327 | 328 | case 'm': 329 | sscanf(optarg,"%o",(unsigned int *)&(open_args.mode)); 330 | break; 331 | 332 | case 'M': 333 | sscanf(optarg,"%o",(unsigned int *)&(open_args2.mode)); 334 | break; 335 | 336 | case 'g': 337 | open_args.group = optarg; 338 | break; 339 | 340 | case 'G': 341 | open_args2.group = optarg; 342 | break; 343 | 344 | case 'L': 345 | vde_ip_log = 1; 346 | 347 | case 'l': 348 | vdeplug_openlog(NULL); 349 | atexit(vdeplug_closelog); 350 | break; 351 | 352 | case 'p' : 353 | pidfile = optarg; 354 | break; 355 | 356 | case 'd' : 357 | daemonize = 1; 358 | break; 359 | 360 | case 'D' : 361 | if (*optarg != 0) 362 | description = optarg; 363 | break; 364 | 365 | default: 366 | usage_and_exit(progname); //implies exit 367 | } 368 | } 369 | 370 | argv += optind; 371 | argc -= optind; 372 | 373 | switch (argc) { 374 | case 0: break; 375 | case 1: vde_url = *argv; 376 | break; 377 | case 2: if (strcmp(argv[0],"=") == 0) 378 | cmdargv = argv+1; 379 | else { 380 | vde_url = argv[0]; 381 | vde_url2 = argv[1]; 382 | } 383 | break; 384 | default: if (strcmp(argv[0],"=") == 0) 385 | cmdargv = argv+1; 386 | else if (strcmp(argv[1],"=") == 0) { 387 | vde_url = argv[0]; 388 | cmdargv = argv+2; 389 | } else 390 | usage_and_exit(progname); //implies exit 391 | break; 392 | } 393 | 394 | if (daemonize != 0) { 395 | if (daemon(0,0) < 0) { 396 | fprintf(stderr,"%s daemonize: %s\n", progname, strerror(errno)); 397 | exit(1); 398 | } 399 | } 400 | 401 | if (pidfile != NULL) 402 | openclosepidfile(pidfile); 403 | 404 | atexit(cleanup); 405 | setsighandlers(cleanup); 406 | 407 | conn = vde_open(vde_url, description, &open_args); 408 | if (conn == NULL) { 409 | fprintf(stderr,"vde_open %s: %s\n",vde_url && *vde_url ? vde_url : "default switch", strerror(errno)); 410 | exit(1); 411 | } 412 | if (vde_url2 != NULL) { 413 | conn2 = vde_open(vde_url2, description, &open_args2); 414 | if (conn2 == NULL) { 415 | fprintf(stderr,"vde_open %s: %s\n",vde_url2 && *vde_url2 ? vde_url2 : "default switch", strerror(errno)); 416 | exit(1); 417 | } 418 | return plug2plug(); 419 | } else if (cmdargv != NULL) 420 | return plug2cmd(cmdargv); 421 | else 422 | return plug2stream(); 423 | } 424 | -------------------------------------------------------------------------------- /srcvdeplug4/vde_plug_iplog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002-2016 Renzo Davoli, University of Bologna 3 | * Modified by Ludovico Gardenghi 2005 4 | * 5 | * iplog: log unique IP addresses seen on a line 6 | * 7 | * VDE is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; If not, see . 19 | * 20 | */ 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #define ETH_ALEN 6 29 | 30 | struct header { 31 | unsigned char dest[ETH_ALEN]; 32 | unsigned char src[ETH_ALEN]; 33 | unsigned char proto[2]; 34 | }; 35 | 36 | union body { 37 | struct { 38 | unsigned char version; 39 | unsigned char filler[11]; 40 | unsigned char ip4src[4]; 41 | unsigned char ip4dst[4]; 42 | } v4; 43 | struct { 44 | unsigned char version; 45 | unsigned char filler[7]; 46 | unsigned char ip6src[16]; 47 | unsigned char ip6dst[16]; 48 | } v6; 49 | struct { 50 | unsigned char priovlan[2]; 51 | } vlan; 52 | }; 53 | 54 | struct addrelem { 55 | struct addrelem *next; 56 | unsigned int len; 57 | char addr[]; 58 | }; 59 | 60 | static unsigned long hash(unsigned int len, unsigned char *addr) 61 | { 62 | unsigned long hash = 5381; 63 | int i; 64 | for (i = 0; i < len; i++) 65 | hash = ((hash << 5) + hash) + addr[i]; 66 | return hash; 67 | } 68 | 69 | static int search_n_add(struct addrelem **scan, unsigned int len, unsigned char *addr) { 70 | struct addrelem *new; 71 | for (; *scan != NULL ; scan = &((*scan)->next)) 72 | if ((*scan)->len == len && memcmp((*scan)->addr,addr,len) == 0) 73 | return 0; 74 | new = malloc(sizeof(struct addrelem) + len); 75 | if (new) { 76 | new->next = NULL; 77 | new->len = len; 78 | memcpy(new->addr, addr, len); 79 | *scan = new; 80 | return 1; 81 | } 82 | return -1; 83 | } 84 | 85 | #define HASH_MASK 511 86 | 87 | void hash_add_n_run(unsigned int len, unsigned char *addr, void *arg, 88 | void (*f)(unsigned int len, unsigned char *addr, void *arg)) { 89 | static struct addrelem **htable; 90 | unsigned long hashkey; 91 | 92 | if (__builtin_expect(htable == NULL, 0)) 93 | htable = calloc(HASH_MASK + 1, sizeof(struct addrelem *)); 94 | 95 | hashkey = hash(len, addr) % HASH_MASK; 96 | 97 | if (search_n_add(&(htable[hashkey]), len, addr) == 1) 98 | f(len, addr, arg); 99 | } 100 | 101 | void printlogv4(unsigned int len, unsigned char *addr, void *arg) { 102 | char straddr[256]; 103 | int *pvlan = arg; 104 | syslog(LOG_INFO, "user %s Real-IP %s has got VDE-IP4 %s on vlan %d", 105 | username, sshremotehost, inet_ntop(AF_INET, addr, straddr, 256), *pvlan); 106 | 107 | } 108 | 109 | void printlogv6(unsigned int len, unsigned char *addr, void *arg) { 110 | char straddr[256]; 111 | int *pvlan = arg; 112 | syslog(LOG_INFO, "user %s Real-IP %s has got VDE-IP6 %s on vlan %d", 113 | username, sshremotehost, inet_ntop(AF_INET6, addr, straddr, 256), *pvlan); 114 | 115 | } 116 | 117 | void vde_ip_check(const unsigned char *buf, int rnx) 118 | { 119 | struct header *ph = (struct header *) buf; 120 | int vlan = 0; 121 | union body *pb; 122 | 123 | pb = (union body *)(ph+1); 124 | if (ph->proto[0] == 0x81 && ph->proto[1] == 0x00) { /*VLAN*/ 125 | vlan = ((pb->vlan.priovlan[0] << 8) + pb->vlan.priovlan[1]) & 0xfff; 126 | pb = (union body *)(((char *)pb)+4); 127 | } 128 | if (ph->proto[0] == 0x08 && ph->proto[1] == 0x00 && 129 | pb->v4.version == 0x45) { 130 | /*v4 */ 131 | hash_add_n_run(4, pb->v4.ip4src, &vlan, printlogv4); 132 | } 133 | else if (ph->proto[0] == 0x86 && ph->proto[1] == 0xdd && 134 | pb->v4.version == 0x60) { 135 | /* v6 */ 136 | hash_add_n_run(16, pb->v6.ip6src, &vlan, printlogv6); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /srcvdeplug4/vde_plug_iplog.h: -------------------------------------------------------------------------------- 1 | #ifndef VDE_PLUG_IPLOG_H 2 | #define VDE_PLUG_IPLOG_H 3 | void vde_ip_check(const unsigned char *buf, int rnx); 4 | 5 | #endif 6 | -------------------------------------------------------------------------------- /srcvdeplug4/vde_plug_log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002-2016 Renzo Davoli, University of Bologna 3 | * Modified by Ludovico Gardenghi 2005 4 | * 5 | * log: vde_plug logging facilities 6 | * 7 | * VDE is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; If not, see . 19 | * 20 | */ 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | char sshremotehost[256]; 34 | char *username; 35 | 36 | static void vdeplug_getdata(void) 37 | { 38 | char *ssh_client; 39 | size_t ip_length; 40 | 41 | //get the login name 42 | struct passwd *callerpwd = getpwuid(getuid()); 43 | username = callerpwd->pw_name; 44 | 45 | openlog("vde_plug", 0, LOG_USER); 46 | 47 | //get the caller IP address 48 | //TNX Giordani-Macchia code from vish.c 49 | if ((ssh_client = getenv("SSH_CLIENT"))!=NULL) 50 | { 51 | for (ip_length = 0; 52 | ip_length=sizeof(sshremotehost)) 56 | ip_length = sizeof(sshremotehost)-1; 57 | memcpy(sshremotehost,ssh_client,ip_length); 58 | sshremotehost[ip_length] = 0; 59 | } 60 | else 61 | strcpy(sshremotehost,"UNKNOWN_IP_ADDRESS"); 62 | } 63 | 64 | void vdeplug_openlog(char *message) { 65 | openlog("vde_plug", 0, LOG_USER); 66 | vdeplug_getdata(); 67 | syslog(LOG_INFO,"%s: user %s IP %s",message ?message : "START",username,sshremotehost); 68 | if (message) 69 | closelog(); 70 | } 71 | 72 | void vdeplug_closelog(void) { 73 | syslog(LOG_INFO,"%s: user %s IP %s","STOP",username,sshremotehost); 74 | closelog(); 75 | } 76 | 77 | -------------------------------------------------------------------------------- /srcvdeplug4/vde_plug_log.h: -------------------------------------------------------------------------------- 1 | #ifndef VDE_PLUG_LOG_H 2 | #define VDE_PLUG_LOG_H 3 | 4 | extern char sshremotehost[256]; 5 | extern char *username; 6 | 7 | void vdeplug_openlog(char *message); 8 | 9 | void vdeplug_closelog(void); 10 | 11 | #endif 12 | --------------------------------------------------------------------------------