1 /* User-kernel network link */
3 /* We will eventually support a variety of methods for extracting
4 packets from the kernel: userv-ipif, ipif on its own (when we run
5 as root), the kernel TUN driver, SLIP to a pty, an external netlink
6 daemon. There is a performance/security tradeoff. */
8 /* When dealing with SLIP (to a pty, or ipif) we have separate rx, tx
9 and client buffers. When receiving we may read() any amount, not
10 just whole packets. When transmitting we need to bytestuff anyway,
11 and may be part-way through receiving. */
13 /* Each netlink device is actually a router, with its own IP
14 address. We do things like decreasing the TTL and recalculating the
15 header checksum, generating ICMP, responding to pings, etc. */
17 /* This is where we have the anti-spoofing paranoia - before sending a
18 packet to the kernel we check that the tunnel it came over could
19 reasonably have produced it. */
21 /* XXX now implement TUN. Kernel needs recompiling. */
27 #include <sys/ioctl.h>
33 #ifdef HAVE_LINUX_IF_H
35 #include <linux/if_tun.h>
38 /* XXX where do we find if_tun on other architectures? */
40 #define DEFAULT_BUFSIZE 2048
41 #define DEFAULT_MTU 1000
42 #define ICMP_BUFSIZE 1024
46 #define SLIP_ESCEND 220
47 #define SLIP_ESCESC 221
49 struct netlink_client {
50 struct subnet_list *networks;
51 netlink_deliver_fn *deliver;
55 struct netlink_client *next;
58 /* Netlink provides one function to the device driver, to call to deliver
59 a packet from the device. The device driver provides one function to
60 netlink, for it to call to deliver a packet to the device. */
64 struct netlink_if ops;
65 void *dst; /* Pointer to host interface state */
67 uint32_t max_start_pad;
69 struct subnet_list networks;
70 uint32_t local_address; /* host interface address */
71 uint32_t secnet_address; /* our own address */
73 struct netlink_client *clients;
74 netlink_deliver_fn *deliver_to_host; /* Provided by driver */
75 struct buffer_if icmp; /* Buffer for assembly of outgoing ICMP */
78 /* Generic IP checksum routine */
79 static inline uint16_t ip_csum(uint8_t *iph,uint32_t count)
81 register uint32_t sum=0;
84 sum+=ntohs(*(uint16_t *)iph);
91 sum=(sum&0xffff)+(sum>>16);
97 * This is a version of ip_compute_csum() optimized for IP headers,
98 * which always checksum on 4 octet boundaries.
100 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
103 static inline uint16_t ip_fast_csum(uint8_t *iph, uint32_t ihl) {
106 __asm__ __volatile__("
125 /* Since the input registers which are loaded with iph and ipl
126 are modified, we must also specify them as outputs, or gcc
127 will assume they contain their original values. */
128 : "=r" (sum), "=r" (iph), "=r" (ihl)
129 : "1" (iph), "2" (ihl));
133 static inline uint16_t ip_fast_csum(uint8_t *iph, uint32_t ihl)
135 return ip_csum(iph,ihl*4);
140 #if defined (WORDS_BIGENDIAN)
156 /* The options start here. */
179 static void netlink_packet_deliver(struct netlink *st, struct buffer_if *buf);
181 static struct icmphdr *netlink_icmp_tmpl(struct netlink *st,
182 uint32_t dest,uint16_t len)
186 BUF_ALLOC(&st->icmp,"netlink_icmp_tmpl");
187 buffer_init(&st->icmp,st->max_start_pad);
188 h=buf_append(&st->icmp,sizeof(*h));
193 h->iph.tot_len=htons(len+(h->iph.ihl*4)+8);
198 h->iph.saddr=htonl(st->secnet_address);
199 h->iph.daddr=htonl(dest);
201 h->iph.check=ip_fast_csum((uint8_t *)&h->iph,h->iph.ihl);
208 /* Fill in the ICMP checksum field correctly */
209 static void netlink_icmp_csum(struct icmphdr *h)
213 len=ntohs(h->iph.tot_len)-(4*h->iph.ihl);
215 h->check=ip_csum(&h->type,len);
219 * An ICMP error message MUST NOT be sent as the result of
222 * * an ICMP error message, or
224 * * a datagram destined to an IP broadcast or IP multicast
227 * * a datagram sent as a link-layer broadcast, or
229 * * a non-initial fragment, or
231 * * a datagram whose source address does not define a single
232 * host -- e.g., a zero address, a loopback address, a
233 * broadcast address, a multicast address, or a Class E
236 static bool_t netlink_icmp_may_reply(struct buffer_if *buf)
241 iph=(struct iphdr *)buf->start;
242 if (iph->protocol==1) return False; /* Overly-broad; we may reply to
243 eg. icmp echo-request */
244 /* How do we spot broadcast destination addresses? */
245 if (ntohs(iph->frag_off)&0x1fff) return False; /* Non-initial fragment */
246 source=ntohl(iph->saddr);
247 if (source==0) return False;
248 if ((source&0xff000000)==0x7f000000) return False;
249 /* How do we spot broadcast source addresses? */
250 if ((source&0xf0000000)==0xe0000000) return False; /* Multicast */
251 if ((source&0xf0000000)==0xf0000000) return False; /* Class E */
255 /* How much of the original IP packet do we include in its ICMP
256 response? The header plus up to 64 bits. */
257 static uint16_t netlink_icmp_reply_len(struct buffer_if *buf)
259 struct iphdr *iph=(struct iphdr *)buf->start;
263 /* We include the first 8 bytes of the packet data, provided they exist */
265 plen=ntohs(iph->tot_len);
266 return (hlen>plen?plen:hlen);
269 static void netlink_icmp_simple(struct netlink *st, struct buffer_if *buf,
270 uint8_t type, uint8_t code)
272 struct iphdr *iph=(struct iphdr *)buf->start;
276 if (netlink_icmp_may_reply(buf)) {
277 len=netlink_icmp_reply_len(buf);
278 h=netlink_icmp_tmpl(st,ntohl(iph->saddr),len);
279 h->type=type; h->code=code;
280 memcpy(buf_append(&st->icmp,len),buf->start,len);
281 netlink_icmp_csum(h);
282 netlink_packet_deliver(st,&st->icmp);
283 BUF_ASSERT_FREE(&st->icmp);
288 * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the
291 * Is the datagram acceptable?
293 * 1. Length at least the size of an ip header
295 * 3. Checksums correctly.
296 * 4. Doesn't have a bogus length
298 static bool_t netlink_check(struct netlink *st, struct buffer_if *buf)
300 struct iphdr *iph=(struct iphdr *)buf->start;
303 if (iph->ihl < 5 || iph->version != 4) {
304 printf("ihl/version check failed\n");
307 if (buf->size < iph->ihl*4) {
308 printf("buffer size check failed\n");
311 if (ip_fast_csum((uint8_t *)iph, iph->ihl)!=0) {
312 printf("checksum failed\n");
315 len=ntohs(iph->tot_len);
316 /* There should be no padding */
317 if (buf->size!=len || len<(iph->ihl<<2)) {
318 printf("length check failed buf->size=%d len=%d\n",buf->size,len);
322 /* XXX check that there's no source route specified */
326 static void netlink_packet_deliver(struct netlink *st, struct buffer_if *buf)
328 struct iphdr *iph=(struct iphdr *)buf->start;
329 uint32_t dest=ntohl(iph->daddr);
330 struct netlink_client *c;
332 BUF_ASSERT_USED(buf);
334 if (dest==st->secnet_address) {
335 Message(M_ERROR,"%s: trying to deliver a packet to myself!\n");
340 for (c=st->clients; c; c=c->next) {
341 if (subnet_match(c->networks,dest)) {
342 if (c->can_deliver) {
343 c->deliver(c->dst,c,buf);
344 BUF_ASSERT_FREE(buf);
346 /* Generate ICMP destination unreachable */
347 netlink_icmp_simple(st,buf,3,0);
353 if (subnet_match(&st->networks,dest)) {
354 st->deliver_to_host(st->dst,NULL,buf);
355 BUF_ASSERT_FREE(buf);
358 Message(M_ERROR,"%s: failed to deliver a packet (bad destination address)"
359 "\nXXX make this message clearer\n");
363 static void netlink_packet_forward(struct netlink *st, struct buffer_if *buf)
365 struct iphdr *iph=(struct iphdr *)buf->start;
367 BUF_ASSERT_USED(buf);
369 /* Packet has already been checked */
371 /* Generate ICMP time exceeded */
372 netlink_icmp_simple(st,buf,11,0);
378 iph->check=ip_fast_csum((uint8_t *)iph,iph->ihl);
380 netlink_packet_deliver(st,buf);
381 BUF_ASSERT_FREE(buf);
384 /* Someone has been foolish enough to address a packet to us. I
385 suppose we should reply to it, just to be polite. */
386 static void netlink_packet_local(struct netlink *st, struct buffer_if *buf)
390 h=(struct icmphdr *)buf->start;
392 if ((ntohs(h->iph.frag_off)&0xbfff)!=0) {
393 Message(M_WARNING,"%s: fragmented packet addressed to us\n",st->name);
398 if (h->iph.protocol==1) {
400 if (h->type==8 && h->code==0) {
401 /* ICMP echo-request. Special case: we re-use the buffer
402 to construct the reply. */
404 h->iph.daddr=h->iph.saddr;
405 h->iph.saddr=htonl(st->secnet_address);
406 h->iph.ttl=255; /* Be nice and bump it up again... */
408 h->iph.check=ip_fast_csum((uint8_t *)h,h->iph.ihl);
409 netlink_icmp_csum(h);
410 netlink_packet_deliver(st,buf);
413 Message(M_WARNING,"%s: unknown incoming ICMP\n",st->name);
415 /* Send ICMP protocol unreachable */
416 netlink_icmp_simple(st,buf,3,2);
424 /* Called by site code when remote packet is available */
425 /* buf is allocated on entry and free on return */
426 static void netlink_from_tunnel(void *sst, void *cst, struct buffer_if *buf)
428 struct netlink *st=sst;
429 struct netlink_client *client=cst;
430 uint32_t source,dest;
433 BUF_ASSERT_USED(buf);
434 if (!netlink_check(st,buf)) {
435 Message(M_WARNING,"%s: bad IP packet from tunnel %s\n",
436 st->name,client->name);
440 iph=(struct iphdr *)buf->start;
442 source=ntohl(iph->saddr);
443 dest=ntohl(iph->daddr);
445 /* Check that the packet source is in 'nets' and its destination is
446 in client->networks */
447 if (!subnet_match(client->networks,source)) {
449 s=ipaddr_to_string(source);
450 d=ipaddr_to_string(dest);
451 Message(M_WARNING,"%s: packet from tunnel %s with bad source address "
452 "(s=%s,d=%s)\n",st->name,client->name,s,d);
457 /* (st->secnet_address needs checking before matching against
458 st->networks because secnet's IP address may not be in the
459 range the host is willing to deal with) */
460 if (dest==st->secnet_address) {
461 netlink_packet_local(st,buf);
462 BUF_ASSERT_FREE(buf);
465 if (!subnet_match(&st->networks,dest)) {
467 s=ipaddr_to_string(source);
468 d=ipaddr_to_string(dest);
469 Message(M_WARNING,"%s: incoming packet from tunnel %s "
470 "with bad destination address "
471 "(s=%s,d=%s)\n",st->name,client->name,s,d);
477 netlink_packet_forward(st,buf);
479 BUF_ASSERT_FREE(buf);
482 /* Called by driver code when packet is received from kernel */
483 /* cid should be NULL */
484 /* buf should be allocated on entry, and is free on return */
485 static void netlink_from_host(void *sst, void *cid, struct buffer_if *buf)
487 struct netlink *st=sst;
488 uint32_t source,dest;
491 BUF_ASSERT_USED(buf);
492 if (!netlink_check(st,buf)) {
493 Message(M_WARNING,"%s: bad IP packet from host\n",
498 iph=(struct iphdr *)buf->start;
500 source=ntohl(iph->saddr);
501 dest=ntohl(iph->daddr);
503 if (!subnet_match(&st->networks,source)) {
505 s=ipaddr_to_string(source);
506 d=ipaddr_to_string(dest);
507 Message(M_WARNING,"%s: outgoing packet with bad source address "
508 "(s=%s,d=%s)\n",st->name,s,d);
513 if (dest==st->secnet_address) {
514 netlink_packet_local(st,buf);
515 BUF_ASSERT_FREE(buf);
518 netlink_packet_forward(st,buf);
519 BUF_ASSERT_FREE(buf);
522 static void netlink_set_delivery(void *sst, void *cid, bool_t can_deliver)
524 struct netlink_client *c=cid;
526 c->can_deliver=can_deliver;
529 static void *netlink_regnets(void *sst, struct subnet_list *nets,
530 netlink_deliver_fn *deliver, void *dst,
531 uint32_t max_start_pad, uint32_t max_end_pad,
532 string_t client_name)
534 struct netlink *st=sst;
535 struct netlink_client *c;
537 Message(M_DEBUG_CONFIG,"netlink_regnets: request for %d networks, "
538 "max_start_pad=%d, max_end_pad=%d\n",
539 nets->entries,max_start_pad,max_end_pad);
541 c=safe_malloc(sizeof(*c),"netlink_regnets");
545 c->name=client_name; /* XXX copy it? */
546 c->can_deliver=False;
549 if (max_start_pad > st->max_start_pad) st->max_start_pad=max_start_pad;
550 if (max_end_pad > st->max_end_pad) st->max_end_pad=max_end_pad;
555 static netlink_deliver_fn *netlink_init(struct netlink *st,
556 void *dst, struct cloc loc,
557 dict_t *dict, string_t description,
558 netlink_deliver_fn *to_host)
561 st->cl.description=description;
562 st->cl.type=CL_NETLINK;
564 st->cl.interface=&st->ops;
566 st->ops.regnets=netlink_regnets;
567 st->ops.deliver=netlink_from_tunnel;
568 st->ops.set_delivery=netlink_set_delivery;
572 st->deliver_to_host=to_host;
574 st->name=dict_read_string(dict,"name",False,"netlink",loc);
575 if (!st->name) st->name=description;
576 dict_read_subnet_list(dict, "networks", True, "netlink", loc,
578 st->local_address=string_to_ipaddr(
579 dict_find_item(dict,"local-address", True, "netlink", loc),"netlink");
580 st->secnet_address=string_to_ipaddr(
581 dict_find_item(dict,"secnet-address", True, "netlink", loc),"netlink");
582 if (!subnet_match(&st->networks,st->local_address)) {
583 cfgfatal(loc,"netlink","local-address must be in local networks\n");
585 st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
586 buffer_new(&st->icmp,ICMP_BUFSIZE);
588 return netlink_from_host;
591 /* Connection to the kernel through userv-ipif */
595 int txfd; /* We transmit to userv */
596 int rxfd; /* We receive from userv */
598 string_t service_user;
599 string_t service_name;
601 struct buffer_if *buff; /* We unstuff received packets into here
602 and send them to the site code. */
604 netlink_deliver_fn *netlink_to_tunnel;
607 static int userv_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
608 int *timeout_io, const struct timeval *tv_now,
611 struct userv *st=sst;
614 fds[0].events=POLLERR; /* Might want to pick up POLLOUT sometime */
616 fds[1].events=POLLIN|POLLERR|POLLHUP;
620 static void userv_afterpoll(void *sst, struct pollfd *fds, int nfds,
621 const struct timeval *tv_now, uint64_t *now)
623 struct userv *st=sst;
624 uint8_t rxbuf[DEFAULT_BUFSIZE];
627 if (fds[1].revents&POLLERR) {
628 printf("userv_afterpoll: hup!\n");
630 if (fds[1].revents&POLLIN) {
631 l=read(st->rxfd,rxbuf,DEFAULT_BUFSIZE);
633 fatal_perror("userv_afterpoll: read(rxfd)");
636 fatal("userv_afterpoll: read(rxfd)=0; userv gone away?\n");
638 /* XXX really crude unstuff code */
639 /* XXX check for buffer overflow */
640 BUF_ASSERT_USED(st->buff);
641 for (i=0; i<l; i++) {
642 if (st->pending_esc) {
643 st->pending_esc=False;
646 *(uint8_t *)buf_append(st->buff,1)=SLIP_END;
649 *(uint8_t *)buf_append(st->buff,1)=SLIP_ESC;
652 fatal("userv_afterpoll: bad SLIP escape character\n");
657 if (st->buff->size>0) {
658 st->netlink_to_tunnel(&st->nl,NULL,
660 BUF_ALLOC(st->buff,"userv_afterpoll");
662 buffer_init(st->buff,st->nl.max_start_pad);
665 st->pending_esc=True;
668 *(uint8_t *)buf_append(st->buff,1)=rxbuf[i];
676 /* Send buf to the kernel. Free buf before returning. */
677 static void userv_deliver_to_kernel(void *sst, void *cid,
678 struct buffer_if *buf)
680 struct userv *st=sst;
681 uint8_t txbuf[DEFAULT_BUFSIZE];
685 BUF_ASSERT_USED(buf);
687 /* Spit the packet at userv-ipif: SLIP start marker, then
688 bytestuff the packet, then SLIP end marker */
689 /* XXX crunchy bytestuff code */
692 for (i=buf->start; i<(buf->start+buf->size); i++) {
696 txbuf[j++]=SLIP_ESCEND;
700 txbuf[j++]=SLIP_ESCESC;
708 if (write(st->txfd,txbuf,j)<0) {
709 fatal_perror("userv_deliver_to_kernel: write()");
714 static void userv_phase_hook(void *sst, uint32_t newphase)
716 struct userv *st=sst;
723 struct netlink_client *c;
726 /* This is where we actually invoke userv - all the networks we'll
727 be using should already have been registered. */
729 addrs=safe_malloc(512,"userv_phase_hook:addrs");
730 snprintf(addrs,512,"%s,%s,%d,slip",ipaddr_to_string(st->nl.local_address),
731 ipaddr_to_string(st->nl.secnet_address),st->nl.mtu);
733 nets=safe_malloc(1024,"userv_phase_hook:nets");
735 for (c=st->nl.clients; c; c=c->next) {
736 for (i=0; i<c->networks->entries; i++) {
737 s=subnet_to_string(&c->networks->list[i]);
743 nets[strlen(nets)-1]=0;
745 Message(M_INFO,"\nuserv_phase_hook: %s %s %s %s %s\n",st->userv_path,
746 st->service_user,st->service_name,addrs,nets);
748 /* Allocate buffer, plus space for padding. Make sure we end up
749 with the start of the packet well-aligned. */
750 /* ALIGN(st->max_start_pad,16); */
751 /* ALIGN(st->max_end_pad,16); */
753 st->pending_esc=False;
756 if (pipe(c_stdin)!=0) {
757 fatal_perror("userv_phase_hook: pipe(c_stdin)");
759 if (pipe(c_stdout)!=0) {
760 fatal_perror("userv_phase_hook: pipe(c_stdout)");
763 st->rxfd=c_stdout[0];
767 fatal_perror("userv_phase_hook: fork()");
772 /* We are the child. Modify our stdin and stdout, then exec userv */
778 /* The arguments are:
782 local-addr,secnet-addr,mtu,protocol
784 argv=malloc(sizeof(*argv)*6);
785 argv[0]=st->userv_path;
786 argv[1]=st->service_user;
787 argv[2]=st->service_name;
791 execvp(st->userv_path,argv);
792 perror("netlink-userv-ipif: execvp");
796 /* We are the parent... */
798 /* Register for poll() */
799 register_for_poll(st, userv_beforepoll, userv_afterpoll, 2, st->nl.name);
802 static list_t *userv_apply(closure_t *self, struct cloc loc, dict_t *context,
809 st=safe_malloc(sizeof(*st),"userv_apply");
811 /* First parameter must be a dict */
812 item=list_elem(args,0);
813 if (!item || item->type!=t_dict)
814 cfgfatal(loc,"userv-ipif","parameter must be a dictionary\n");
816 dict=item->data.dict;
818 st->netlink_to_tunnel=
819 netlink_init(&st->nl,st,loc,dict,
820 "netlink-userv-ipif",userv_deliver_to_kernel);
822 st->userv_path=dict_read_string(dict,"userv-path",False,"userv-netlink",
824 st->service_user=dict_read_string(dict,"service-user",False,
825 "userv-netlink",loc);
826 st->service_name=dict_read_string(dict,"service-name",False,
827 "userv-netlink",loc);
828 if (!st->userv_path) st->userv_path="userv";
829 if (!st->service_user) st->service_user="root";
830 if (!st->service_name) st->service_name="ipif";
831 st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"userv-netlink",loc);
832 BUF_ALLOC(st->buff,"netlink:userv_apply");
834 st->rxfd=-1; st->txfd=-1;
835 add_hook(PHASE_DROPPRIV,userv_phase_hook,st);
837 return new_closure(&st->nl.cl);
840 /* Connection to the kernel through the universal TUN/TAP driver */
845 string_t device_path;
846 string_t interface_name;
847 string_t ifconfig_path;
849 struct buffer_if *buff; /* We receive packets into here
850 and send them to the netlink code. */
851 netlink_deliver_fn *netlink_to_tunnel;
854 static int tun_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
855 int *timeout_io, const struct timeval *tv_now,
861 fds[0].events=POLLIN|POLLERR|POLLHUP;
865 static void tun_afterpoll(void *sst, struct pollfd *fds, int nfds,
866 const struct timeval *tv_now, uint64_t *now)
871 if (fds[0].revents&POLLERR) {
872 printf("tun_afterpoll: hup!\n");
874 if (fds[0].revents&POLLIN) {
875 BUF_ALLOC(st->buff,"tun_afterpoll");
876 buffer_init(st->buff,st->nl.max_start_pad);
877 l=read(st->fd,st->buff->start,st->buff->len-st->nl.max_start_pad);
879 fatal_perror("tun_afterpoll: read()");
882 fatal("tun_afterpoll: read()=0; device gone away?\n");
886 st->netlink_to_tunnel(&st->nl,NULL,st->buff);
887 BUF_ASSERT_FREE(st->buff);
892 static void tun_deliver_to_kernel(void *sst, void *cid,
893 struct buffer_if *buf)
897 BUF_ASSERT_USED(buf);
899 /* No error checking, because we'd just throw the packet away anyway */
900 write(st->fd,buf->start,buf->size);
904 static void tun_phase_hook(void *sst, uint32_t newphase)
907 string_t hostaddr,secnetaddr;
909 string_t network,mask;
910 struct netlink_client *c;
913 /* All the networks we'll be using have been registered. Invoke ifconfig
914 to set the TUN device's address, and route to add routes to all
917 hostaddr=ipaddr_to_string(st->nl.local_address);
918 secnetaddr=ipaddr_to_string(st->nl.secnet_address);
919 snprintf(mtu,6,"%d",st->nl.mtu);
922 sys_cmd(st->ifconfig_path,"ifconfig",st->interface_name,
923 hostaddr,"netmask","255.255.255.255","-broadcast",
924 "pointopoint",secnetaddr,"mtu",mtu,"up",(char *)0);
926 for (c=st->nl.clients; c; c=c->next) {
927 for (i=0; i<c->networks->entries; i++) {
928 network=ipaddr_to_string(c->networks->list[i].prefix);
929 mask=ipaddr_to_string(c->networks->list[i].mask);
930 sys_cmd(st->route_path,"route","add","-net",network,
931 "netmask",mask,"gw",secnetaddr,(char *)0);
935 /* Register for poll() */
936 register_for_poll(st, tun_beforepoll, tun_afterpoll, 1, st->nl.name);
939 #ifdef HAVE_LINUX_IF_H
940 static list_t *tun_apply(closure_t *self, struct cloc loc, dict_t *context,
948 st=safe_malloc(sizeof(*st),"tun_apply");
950 /* First parameter must be a dict */
951 item=list_elem(args,0);
952 if (!item || item->type!=t_dict)
953 cfgfatal(loc,"tun","parameter must be a dictionary\n");
955 dict=item->data.dict;
957 st->netlink_to_tunnel=
958 netlink_init(&st->nl,st,loc,dict,
959 "netlink-tun",tun_deliver_to_kernel);
961 st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
962 st->interface_name=dict_read_string(dict,"interface",False,
964 st->ifconfig_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
965 st->route_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
967 if (!st->device_path) st->device_path="/dev/net/tun";
968 if (!st->ifconfig_path) st->ifconfig_path="ifconfig";
969 if (!st->route_path) st->route_path="route";
970 st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"tun-netlink",loc);
972 /* New TUN interface: open the device, then do ioctl TUNSETIFF
973 to set or find out the network interface name. */
974 st->fd=open(st->device_path,O_RDWR);
976 fatal_perror("%s: can't open device file %s",st->nl.name,
979 memset(&ifr,0,sizeof(ifr));
980 ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Just send/receive IP packets,
982 if (st->interface_name)
983 strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ);
984 if (ioctl(st->fd,TUNSETIFF,&ifr)<0) {
985 fatal_perror("%s: ioctl(TUNSETIFF)",st->nl.name);
987 if (!st->interface_name) {
988 st->interface_name=safe_malloc(strlen(ifr.ifr_name)+1,"tun_apply");
989 strcpy(st->interface_name,ifr.ifr_name);
990 Message(M_INFO,"%s: allocated network interface %s\n",st->nl.name,
994 add_hook(PHASE_DROPPRIV,tun_phase_hook,st);
996 return new_closure(&st->nl.cl);
998 #endif /* HAVE_LINUX_IF_H */
1000 static list_t *tun_old_apply(closure_t *self, struct cloc loc, dict_t *context,
1006 bool_t search_for_if;
1008 st=safe_malloc(sizeof(*st),"tun_old_apply");
1010 Message(M_WARNING,"the tun-old code has never been tested. Please report "
1011 "success or failure to steve@greenend.org.uk\n");
1013 /* First parameter must be a dict */
1014 item=list_elem(args,0);
1015 if (!item || item->type!=t_dict)
1016 cfgfatal(loc,"tun","parameter must be a dictionary\n");
1018 dict=item->data.dict;
1020 st->netlink_to_tunnel=
1021 netlink_init(&st->nl,st,loc,dict,
1022 "netlink-tun",tun_deliver_to_kernel);
1024 st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
1025 st->interface_name=dict_read_string(dict,"interface",False,
1027 search_for_if=dict_read_bool(dict,"interface-search",False,"tun-netlink",
1028 loc,st->device_path==NULL);
1029 st->ifconfig_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
1030 st->route_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
1032 if (!st->device_path) st->device_path="/dev/tun";
1033 if (!st->ifconfig_path) st->ifconfig_path="ifconfig";
1034 if (!st->route_path) st->route_path="route";
1035 st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"tun-netlink",loc);
1037 /* Old TUN interface: the network interface name depends on which
1038 /dev/tunX file we open. If 'interface-search' is set to true, treat
1039 'device' as the prefix and try numbers from 0--255. If it's set
1040 to false, treat 'device' as the whole name, and require than an
1041 appropriate interface name be specified. */
1042 if (search_for_if) {
1046 if (st->interface_name) {
1047 cfgfatal(loc,"tun-old","you may not specify an interface name "
1048 "in interface-search mode\n");
1050 dname=safe_malloc(strlen(st->device_path)+4,"tun_old_apply");
1051 st->interface_name=safe_malloc(8,"tun_old_apply");
1053 for (i=0; i<255; i++) {
1054 sprintf(dname,"%s%d",st->device_path,i);
1055 if ((st->fd=open(dname,O_RDWR))>0) {
1056 sprintf(st->interface_name,"tun%d",i);
1057 Message(M_INFO,"%s: allocated network interface %s "
1058 "through %s\n",st->nl.name,st->interface_name,dname);
1063 fatal("%s: unable to open any TUN device (%s...)\n",
1064 st->nl.name,st->device_path);
1067 if (!st->interface_name) {
1068 cfgfatal(loc,"tun-old","you must specify an interface name "
1069 "when you explicitly specify a TUN device file\n");
1071 st->fd=open(st->device_path,O_RDWR);
1073 fatal_perror("%s: unable to open TUN device file %s",
1074 st->nl.name,st->device_path);
1078 add_hook(PHASE_DROPPRIV,tun_phase_hook,st);
1080 return new_closure(&st->nl.cl);
1083 /* No connection to the kernel at all... */
1089 static void null_deliver(void *sst, void *cid, struct buffer_if *buf)
1094 static list_t *null_apply(closure_t *self, struct cloc loc, dict_t *context,
1101 st=safe_malloc(sizeof(*st),"null_apply");
1103 item=list_elem(args,0);
1104 if (!item || item->type!=t_dict)
1105 cfgfatal(loc,"null-netlink","parameter must be a dictionary\n");
1107 dict=item->data.dict;
1109 netlink_init(&st->nl,st,loc,dict,"null-netlink",null_deliver);
1111 return new_closure(&st->nl.cl);
1114 init_module netlink_module;
1115 void netlink_module(dict_t *dict)
1117 add_closure(dict,"userv-ipif",userv_apply);
1118 #ifdef HAVE_LINUX_IF_H
1119 add_closure(dict,"tun",tun_apply);
1121 add_closure(dict,"tun-old",tun_old_apply);
1122 add_closure(dict,"null-netlink",null_apply);
1125 add_closure(dict,"pty-slip",ptyslip_apply);
1126 add_closure(dict,"slipd",slipd_apply);