123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128(*
* Copyright (c) 2010-2013 Anil Madhavapeddy <anil@recoil.org>
* Copyright (c) 2013 Vincent Bernardoff <vb@luminar.eu.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)typekind=Tap|Tunexternalopentun_stub:string->kind->bool->int->int->int->Unix.file_descr*string="tun_opendev_byte""tun_opendev"externalget_macaddr:string->string="get_macaddr"externalget_mtu:string->int="get_mtu"externalset_ipv4:string->string->string->unit="set_ipv4"externalset_up_and_running:string->unit="set_up_and_running"externalget_ifnamsiz:unit->int="get_ifnamsiz"letopen_kind?(pi=false)?persist?(user=-1)?(group=-1)?(devname="")()=letpersist_int=matchpersistwith|None->-1|Somefalse->0|Sometrue->1inopentun_stubdevnamekindpipersist_intusergroupletopentun=open_Tunletopentap=open_Tap(* Closing is just opening an existing device in non-persistent
mode *)letclosetundevname=ignore(opentun~devname~persist:false())letclosetapdevname=ignore(opentap~devname~persist:false())letset_ipv4?(netmask=Ipaddr.V4.Prefix.global)devnamev4addr=letopenIpaddr.V4inset_ipv4devname(to_octetsv4addr)(to_octets(Prefix.netmasknetmask))letget_macaddriface=Macaddr.of_octets_exn(get_macaddriface)moduleOpt=structlet(>|=)xf=matchxwithSomev->Some(fv)|None->Noneletrun=function|Somex->x|None->raiseNot_foundendmoduleStruct_ifaddrs=structtypet={name:string;sa_family:int;addr:stringoption;mask:stringoption;brd:stringoption;}typeptr_texternalgetifaddrs_stub:unit->ptr_toption="getifaddrs_stub"externalfreeifaddrs_stub:ptr_t->unit="freeifaddrs_stub"externaliface_get:ptr_t->t="iface_get"externaliface_next:ptr_t->ptr_toption="iface_next"letto_t't=letopenIpaddrinletopenOptinmatcht.sa_familywith|0->letaddress=run(t.addr>|=funv->V4.of_octets_exnv)andnetmask=run(t.mask>|=funv->V4.of_octets_exnv)inSome(t.name,`V4(V4.Prefix.of_netmask_exn~netmask~address))|1->letaddress=run(t.addr>|=funv->V6.of_octets_exnv)andnetmask=run(t.mask>|=funv->V6.of_octets_exnv)inSome(t.name,`V6(V6.Prefix.of_netmask_exn~netmask~address))|_->Noneendletgetifaddrs()=letopenStruct_ifaddrsinmatchgetifaddrs_stub()with|None->[]|Somestart->letrecloopaccptr=letacc=matchto_t'(iface_getptr)with|None->acc|Somet'->t'::accinmatchiface_nextptrwith|None->freeifaddrs_stubstart;acc|Somep->loopaccpinloop[]startletfilter_mapfl=List.fold_left(funav->matchfvwithSomev'->v'::a|None->a)[]lletgetifaddrs_v4()=filter_map(function(ifn,`V4a)->Some(ifn,a)|_->None)@@getifaddrs()letgetifaddrs_v6()=filter_map(function(ifn,`V6a)->Some(ifn,a)|_->None)@@getifaddrs()letaddrs_of_ifnameifname=filter_map(fun(ifn,a)->ififn=ifnamethenSomeaelseNone)@@getifaddrs()letv4_of_ifnameifname=filter_map(fun(ifn,a)->ififn=ifnamethenSomeaelseNone)@@getifaddrs_v4()letv6_of_ifnameifname=filter_map(fun(ifn,a)->ififn=ifnamethenSomeaelseNone)@@getifaddrs_v6()