1 /* User-kernel network link */
3 /* We support a variety of methods for extracting packets from the
4 kernel: userv-ipif, ipif on its own (when we run as root), the
5 kernel TUN driver. Possible future methods: SLIP to a pty, an
6 external netlink daemon. There is a performance/security
9 /* When dealing with SLIP (to a pty, or ipif) we have separate rx, tx
10 and client buffers. When receiving we may read() any amount, not
11 just whole packets. When transmitting we need to bytestuff anyway,
12 and may be part-way through receiving. */
14 /* Each netlink device is actually a router, with its own IP address.
15 We do things like decreasing the TTL and recalculating the header
16 checksum, generating ICMP, responding to pings, etc. */
18 /* This is where we have the anti-spoofing paranoia - before sending a
19 packet to the kernel we check that the tunnel it came over could
20 reasonably have produced it. */
27 #include <sys/ioctl.h>
30 #ifdef HAVE_LINUX_IF_H
32 #include <linux/if_tun.h>
35 /* XXX where do we find if_tun on other platforms? */
37 #define DEFAULT_BUFSIZE 2048
38 #define DEFAULT_MTU 1000
39 #define ICMP_BUFSIZE 1024
43 #define SLIP_ESCEND 220
44 #define SLIP_ESCESC 221
46 struct netlink_client {
47 struct subnet_list *networks;
48 netlink_deliver_fn *deliver;
52 struct netlink_client *next;
55 /* Netlink provides one function to the device driver, to call to deliver
56 a packet from the device. The device driver provides one function to
57 netlink, for it to call to deliver a packet to the device. */
61 struct netlink_if ops;
62 void *dst; /* Pointer to host interface state */
64 uint32_t max_start_pad;
66 struct subnet_list networks;
67 struct subnet_list exclude_remote_networks;
68 uint32_t local_address; /* host interface address */
69 uint32_t secnet_address; /* our own address */
71 struct netlink_client *clients;
72 netlink_deliver_fn *deliver_to_host; /* Provided by driver */
73 struct buffer_if icmp; /* Buffer for assembly of outgoing ICMP */
76 /* Generic IP checksum routine */
77 static inline uint16_t ip_csum(uint8_t *iph,uint32_t count)
79 register uint32_t sum=0;
82 sum+=ntohs(*(uint16_t *)iph);
89 sum=(sum&0xffff)+(sum>>16);
95 * This is a version of ip_compute_csum() optimized for IP headers,
96 * which always checksum on 4 octet boundaries.
98 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
101 static inline uint16_t ip_fast_csum(uint8_t *iph, uint32_t ihl) {
104 __asm__ __volatile__("
123 /* Since the input registers which are loaded with iph and ipl
124 are modified, we must also specify them as outputs, or gcc
125 will assume they contain their original values. */
126 : "=r" (sum), "=r" (iph), "=r" (ihl)
127 : "1" (iph), "2" (ihl));
131 static inline uint16_t ip_fast_csum(uint8_t *iph, uint32_t ihl)
133 return ip_csum(iph,ihl*4);
138 #if defined (WORDS_BIGENDIAN)
154 /* The options start here. */
177 static void netlink_packet_deliver(struct netlink *st, struct buffer_if *buf);
179 static struct icmphdr *netlink_icmp_tmpl(struct netlink *st,
180 uint32_t dest,uint16_t len)
184 BUF_ALLOC(&st->icmp,"netlink_icmp_tmpl");
185 buffer_init(&st->icmp,st->max_start_pad);
186 h=buf_append(&st->icmp,sizeof(*h));
191 h->iph.tot_len=htons(len+(h->iph.ihl*4)+8);
196 h->iph.saddr=htonl(st->secnet_address);
197 h->iph.daddr=htonl(dest);
199 h->iph.check=ip_fast_csum((uint8_t *)&h->iph,h->iph.ihl);
206 /* Fill in the ICMP checksum field correctly */
207 static void netlink_icmp_csum(struct icmphdr *h)
211 len=ntohs(h->iph.tot_len)-(4*h->iph.ihl);
213 h->check=ip_csum(&h->type,len);
217 * An ICMP error message MUST NOT be sent as the result of
220 * * an ICMP error message, or
222 * * a datagram destined to an IP broadcast or IP multicast
225 * * a datagram sent as a link-layer broadcast, or
227 * * a non-initial fragment, or
229 * * a datagram whose source address does not define a single
230 * host -- e.g., a zero address, a loopback address, a
231 * broadcast address, a multicast address, or a Class E
234 static bool_t netlink_icmp_may_reply(struct buffer_if *buf)
239 iph=(struct iphdr *)buf->start;
240 if (iph->protocol==1) return False; /* Overly-broad; we may reply to
241 eg. icmp echo-request */
242 /* How do we spot broadcast destination addresses? */
243 if (ntohs(iph->frag_off)&0x1fff) return False; /* Non-initial fragment */
244 source=ntohl(iph->saddr);
245 if (source==0) return False;
246 if ((source&0xff000000)==0x7f000000) return False;
247 /* How do we spot broadcast source addresses? */
248 if ((source&0xf0000000)==0xe0000000) return False; /* Multicast */
249 if ((source&0xf0000000)==0xf0000000) return False; /* Class E */
253 /* How much of the original IP packet do we include in its ICMP
254 response? The header plus up to 64 bits. */
255 static uint16_t netlink_icmp_reply_len(struct buffer_if *buf)
257 struct iphdr *iph=(struct iphdr *)buf->start;
261 /* We include the first 8 bytes of the packet data, provided they exist */
263 plen=ntohs(iph->tot_len);
264 return (hlen>plen?plen:hlen);
267 static void netlink_icmp_simple(struct netlink *st, struct buffer_if *buf,
268 uint8_t type, uint8_t code)
270 struct iphdr *iph=(struct iphdr *)buf->start;
274 if (netlink_icmp_may_reply(buf)) {
275 len=netlink_icmp_reply_len(buf);
276 h=netlink_icmp_tmpl(st,ntohl(iph->saddr),len);
277 h->type=type; h->code=code;
278 memcpy(buf_append(&st->icmp,len),buf->start,len);
279 netlink_icmp_csum(h);
280 netlink_packet_deliver(st,&st->icmp);
281 BUF_ASSERT_FREE(&st->icmp);
286 * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the
289 * Is the datagram acceptable?
291 * 1. Length at least the size of an ip header
293 * 3. Checksums correctly.
294 * 4. Doesn't have a bogus length
296 static bool_t netlink_check(struct netlink *st, struct buffer_if *buf)
298 struct iphdr *iph=(struct iphdr *)buf->start;
301 if (iph->ihl < 5 || iph->version != 4) {
302 printf("ihl/version check failed\n");
305 if (buf->size < iph->ihl*4) {
306 printf("buffer size check failed\n");
309 if (ip_fast_csum((uint8_t *)iph, iph->ihl)!=0) {
310 printf("checksum failed\n");
313 len=ntohs(iph->tot_len);
314 /* There should be no padding */
315 if (buf->size!=len || len<(iph->ihl<<2)) {
316 printf("length check failed buf->size=%d len=%d\n",buf->size,len);
320 /* XXX check that there's no source route specified */
324 static void netlink_packet_deliver(struct netlink *st, struct buffer_if *buf)
326 struct iphdr *iph=(struct iphdr *)buf->start;
327 uint32_t dest=ntohl(iph->daddr);
328 struct netlink_client *c;
330 BUF_ASSERT_USED(buf);
332 if (dest==st->secnet_address) {
333 Message(M_ERROR,"%s: trying to deliver a packet to myself!\n");
338 for (c=st->clients; c; c=c->next) {
339 if (subnet_match(c->networks,dest)) {
340 if (c->can_deliver) {
341 c->deliver(c->dst,c,buf);
342 BUF_ASSERT_FREE(buf);
344 /* Generate ICMP destination unreachable */
345 netlink_icmp_simple(st,buf,3,0);
351 if (subnet_match(&st->networks,dest)) {
352 st->deliver_to_host(st->dst,NULL,buf);
353 BUF_ASSERT_FREE(buf);
356 Message(M_ERROR,"%s: failed to deliver a packet (bad destination address)"
357 "\nXXX make this message clearer\n");
361 static void netlink_packet_forward(struct netlink *st, struct buffer_if *buf)
363 struct iphdr *iph=(struct iphdr *)buf->start;
365 BUF_ASSERT_USED(buf);
367 /* Packet has already been checked */
369 /* Generate ICMP time exceeded */
370 netlink_icmp_simple(st,buf,11,0);
376 iph->check=ip_fast_csum((uint8_t *)iph,iph->ihl);
378 netlink_packet_deliver(st,buf);
379 BUF_ASSERT_FREE(buf);
382 /* Someone has been foolish enough to address a packet to us. I
383 suppose we should reply to it, just to be polite. */
384 static void netlink_packet_local(struct netlink *st, struct buffer_if *buf)
388 h=(struct icmphdr *)buf->start;
390 if ((ntohs(h->iph.frag_off)&0xbfff)!=0) {
391 Message(M_WARNING,"%s: fragmented packet addressed to us\n",st->name);
396 if (h->iph.protocol==1) {
398 if (h->type==8 && h->code==0) {
399 /* ICMP echo-request. Special case: we re-use the buffer
400 to construct the reply. */
402 h->iph.daddr=h->iph.saddr;
403 h->iph.saddr=htonl(st->secnet_address);
404 h->iph.ttl=255; /* Be nice and bump it up again... */
406 h->iph.check=ip_fast_csum((uint8_t *)h,h->iph.ihl);
407 netlink_icmp_csum(h);
408 netlink_packet_deliver(st,buf);
411 Message(M_WARNING,"%s: unknown incoming ICMP\n",st->name);
413 /* Send ICMP protocol unreachable */
414 netlink_icmp_simple(st,buf,3,2);
422 /* Called by site code when remote packet is available */
423 /* buf is allocated on entry and free on return */
424 static void netlink_from_tunnel(void *sst, void *cst, struct buffer_if *buf)
426 struct netlink *st=sst;
427 struct netlink_client *client=cst;
428 uint32_t source,dest;
431 BUF_ASSERT_USED(buf);
432 if (!netlink_check(st,buf)) {
433 Message(M_WARNING,"%s: bad IP packet from tunnel %s\n",
434 st->name,client->name);
438 iph=(struct iphdr *)buf->start;
440 source=ntohl(iph->saddr);
441 dest=ntohl(iph->daddr);
443 /* Check that the packet source is in 'nets' and its destination is
444 in client->networks */
445 if (!subnet_match(client->networks,source)) {
447 s=ipaddr_to_string(source);
448 d=ipaddr_to_string(dest);
449 Message(M_WARNING,"%s: packet from tunnel %s with bad source address "
450 "(s=%s,d=%s)\n",st->name,client->name,s,d);
455 /* (st->secnet_address needs checking before matching against
456 st->networks because secnet's IP address may not be in the
457 range the host is willing to deal with) */
458 if (dest==st->secnet_address) {
459 netlink_packet_local(st,buf);
460 BUF_ASSERT_FREE(buf);
463 if (!subnet_match(&st->networks,dest)) {
465 s=ipaddr_to_string(source);
466 d=ipaddr_to_string(dest);
467 Message(M_WARNING,"%s: incoming packet from tunnel %s "
468 "with bad destination address "
469 "(s=%s,d=%s)\n",st->name,client->name,s,d);
475 netlink_packet_forward(st,buf);
477 BUF_ASSERT_FREE(buf);
480 /* Called by driver code when packet is received from kernel */
481 /* cid should be NULL */
482 /* buf should be allocated on entry, and is free on return */
483 static void netlink_from_host(void *sst, void *cid, struct buffer_if *buf)
485 struct netlink *st=sst;
486 uint32_t source,dest;
489 BUF_ASSERT_USED(buf);
490 if (!netlink_check(st,buf)) {
491 Message(M_WARNING,"%s: bad IP packet from host\n",
496 iph=(struct iphdr *)buf->start;
498 source=ntohl(iph->saddr);
499 dest=ntohl(iph->daddr);
501 if (!subnet_match(&st->networks,source)) {
503 s=ipaddr_to_string(source);
504 d=ipaddr_to_string(dest);
505 Message(M_WARNING,"%s: outgoing packet with bad source address "
506 "(s=%s,d=%s)\n",st->name,s,d);
511 if (dest==st->secnet_address) {
512 netlink_packet_local(st,buf);
513 BUF_ASSERT_FREE(buf);
516 netlink_packet_forward(st,buf);
517 BUF_ASSERT_FREE(buf);
520 static void netlink_set_delivery(void *sst, void *cid, bool_t can_deliver)
522 struct netlink_client *c=cid;
524 c->can_deliver=can_deliver;
527 static void *netlink_regnets(void *sst, struct subnet_list *nets,
528 netlink_deliver_fn *deliver, void *dst,
529 uint32_t max_start_pad, uint32_t max_end_pad,
530 string_t client_name)
532 struct netlink *st=sst;
533 struct netlink_client *c;
535 Message(M_DEBUG_CONFIG,"netlink_regnets: request for %d networks, "
536 "max_start_pad=%d, max_end_pad=%d\n",
537 nets->entries,max_start_pad,max_end_pad);
539 /* Check that nets does not intersect with st->networks or
540 st->exclude_remote_networks; refuse to register if it does. */
541 if (subnet_lists_intersect(&st->networks,nets)) {
542 Message(M_ERROR,"%s: site %s specifies networks that "
543 "intersect with our local networks\n",st->name,client_name);
546 if (subnet_lists_intersect(&st->exclude_remote_networks,nets)) {
547 Message(M_ERROR,"%s: site %s specifies networks that "
548 "intersect with the explicitly excluded remote networks\n",
549 st->name,client_name);
553 c=safe_malloc(sizeof(*c),"netlink_regnets");
557 c->name=client_name; /* XXX copy it? */
558 c->can_deliver=False;
561 if (max_start_pad > st->max_start_pad) st->max_start_pad=max_start_pad;
562 if (max_end_pad > st->max_end_pad) st->max_end_pad=max_end_pad;
567 static netlink_deliver_fn *netlink_init(struct netlink *st,
568 void *dst, struct cloc loc,
569 dict_t *dict, string_t description,
570 netlink_deliver_fn *to_host)
573 st->cl.description=description;
574 st->cl.type=CL_NETLINK;
576 st->cl.interface=&st->ops;
578 st->ops.regnets=netlink_regnets;
579 st->ops.deliver=netlink_from_tunnel;
580 st->ops.set_delivery=netlink_set_delivery;
584 st->deliver_to_host=to_host;
586 st->name=dict_read_string(dict,"name",False,"netlink",loc);
587 if (!st->name) st->name=description;
588 dict_read_subnet_list(dict, "networks", True, "netlink", loc,
590 dict_read_subnet_list(dict, "exclude-remote-networks", False, "netlink",
591 loc, &st->exclude_remote_networks);
592 /* local-address and secnet-address do not have to be in local-networks;
593 however, they should be advertised in the 'sites' file for the
595 st->local_address=string_to_ipaddr(
596 dict_find_item(dict,"local-address", True, "netlink", loc),"netlink");
597 st->secnet_address=string_to_ipaddr(
598 dict_find_item(dict,"secnet-address", True, "netlink", loc),"netlink");
599 st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
600 buffer_new(&st->icmp,ICMP_BUFSIZE);
602 return netlink_from_host;
605 /* Connection to the kernel through userv-ipif */
609 int txfd; /* We transmit to userv */
610 int rxfd; /* We receive from userv */
612 string_t service_user;
613 string_t service_name;
615 struct buffer_if *buff; /* We unstuff received packets into here
616 and send them to the site code. */
618 netlink_deliver_fn *netlink_to_tunnel;
621 static int userv_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
622 int *timeout_io, const struct timeval *tv_now,
625 struct userv *st=sst;
628 fds[0].events=POLLERR; /* Might want to pick up POLLOUT sometime */
630 fds[1].events=POLLIN|POLLERR|POLLHUP;
634 static void userv_afterpoll(void *sst, struct pollfd *fds, int nfds,
635 const struct timeval *tv_now, uint64_t *now)
637 struct userv *st=sst;
638 uint8_t rxbuf[DEFAULT_BUFSIZE];
641 if (fds[1].revents&POLLERR) {
642 printf("userv_afterpoll: hup!\n");
644 if (fds[1].revents&POLLIN) {
645 l=read(st->rxfd,rxbuf,DEFAULT_BUFSIZE);
647 fatal_perror("userv_afterpoll: read(rxfd)");
650 fatal("userv_afterpoll: read(rxfd)=0; userv gone away?\n");
652 /* XXX really crude unstuff code */
653 /* XXX check for buffer overflow */
654 BUF_ASSERT_USED(st->buff);
655 for (i=0; i<l; i++) {
656 if (st->pending_esc) {
657 st->pending_esc=False;
660 *(uint8_t *)buf_append(st->buff,1)=SLIP_END;
663 *(uint8_t *)buf_append(st->buff,1)=SLIP_ESC;
666 fatal("userv_afterpoll: bad SLIP escape character\n");
671 if (st->buff->size>0) {
672 st->netlink_to_tunnel(&st->nl,NULL,
674 BUF_ALLOC(st->buff,"userv_afterpoll");
676 buffer_init(st->buff,st->nl.max_start_pad);
679 st->pending_esc=True;
682 *(uint8_t *)buf_append(st->buff,1)=rxbuf[i];
690 /* Send buf to the kernel. Free buf before returning. */
691 static void userv_deliver_to_kernel(void *sst, void *cid,
692 struct buffer_if *buf)
694 struct userv *st=sst;
695 uint8_t txbuf[DEFAULT_BUFSIZE];
699 BUF_ASSERT_USED(buf);
701 /* Spit the packet at userv-ipif: SLIP start marker, then
702 bytestuff the packet, then SLIP end marker */
703 /* XXX crunchy bytestuff code */
706 for (i=buf->start; i<(buf->start+buf->size); i++) {
710 txbuf[j++]=SLIP_ESCEND;
714 txbuf[j++]=SLIP_ESCESC;
722 if (write(st->txfd,txbuf,j)<0) {
723 fatal_perror("userv_deliver_to_kernel: write()");
728 static void userv_phase_hook(void *sst, uint32_t newphase)
730 struct userv *st=sst;
737 struct netlink_client *c;
740 /* This is where we actually invoke userv - all the networks we'll
741 be using should already have been registered. */
743 addrs=safe_malloc(512,"userv_phase_hook:addrs");
744 snprintf(addrs,512,"%s,%s,%d,slip",ipaddr_to_string(st->nl.local_address),
745 ipaddr_to_string(st->nl.secnet_address),st->nl.mtu);
747 nets=safe_malloc(1024,"userv_phase_hook:nets");
749 for (c=st->nl.clients; c; c=c->next) {
750 for (i=0; i<c->networks->entries; i++) {
751 s=subnet_to_string(&c->networks->list[i]);
757 nets[strlen(nets)-1]=0;
759 Message(M_INFO,"\nuserv_phase_hook: %s %s %s %s %s\n",st->userv_path,
760 st->service_user,st->service_name,addrs,nets);
762 /* Allocate buffer, plus space for padding. Make sure we end up
763 with the start of the packet well-aligned. */
764 /* ALIGN(st->max_start_pad,16); */
765 /* ALIGN(st->max_end_pad,16); */
767 st->pending_esc=False;
770 if (pipe(c_stdin)!=0) {
771 fatal_perror("userv_phase_hook: pipe(c_stdin)");
773 if (pipe(c_stdout)!=0) {
774 fatal_perror("userv_phase_hook: pipe(c_stdout)");
777 st->rxfd=c_stdout[0];
781 fatal_perror("userv_phase_hook: fork()");
786 /* We are the child. Modify our stdin and stdout, then exec userv */
792 /* The arguments are:
796 local-addr,secnet-addr,mtu,protocol
798 argv=malloc(sizeof(*argv)*6);
799 argv[0]=st->userv_path;
800 argv[1]=st->service_user;
801 argv[2]=st->service_name;
805 execvp(st->userv_path,argv);
806 perror("netlink-userv-ipif: execvp");
810 /* We are the parent... */
812 /* Register for poll() */
813 register_for_poll(st, userv_beforepoll, userv_afterpoll, 2, st->nl.name);
816 static list_t *userv_apply(closure_t *self, struct cloc loc, dict_t *context,
823 st=safe_malloc(sizeof(*st),"userv_apply");
825 /* First parameter must be a dict */
826 item=list_elem(args,0);
827 if (!item || item->type!=t_dict)
828 cfgfatal(loc,"userv-ipif","parameter must be a dictionary\n");
830 dict=item->data.dict;
832 st->netlink_to_tunnel=
833 netlink_init(&st->nl,st,loc,dict,
834 "netlink-userv-ipif",userv_deliver_to_kernel);
836 st->userv_path=dict_read_string(dict,"userv-path",False,"userv-netlink",
838 st->service_user=dict_read_string(dict,"service-user",False,
839 "userv-netlink",loc);
840 st->service_name=dict_read_string(dict,"service-name",False,
841 "userv-netlink",loc);
842 if (!st->userv_path) st->userv_path="userv";
843 if (!st->service_user) st->service_user="root";
844 if (!st->service_name) st->service_name="ipif";
845 st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"userv-netlink",loc);
846 BUF_ALLOC(st->buff,"netlink:userv_apply");
848 st->rxfd=-1; st->txfd=-1;
849 add_hook(PHASE_DROPPRIV,userv_phase_hook,st);
851 return new_closure(&st->nl.cl);
854 /* Connection to the kernel through the universal TUN/TAP driver */
859 string_t device_path;
860 string_t interface_name;
861 string_t ifconfig_path;
864 bool_t search_for_if; /* Applies to tun-old only */
865 struct buffer_if *buff; /* We receive packets into here
866 and send them to the netlink code. */
867 netlink_deliver_fn *netlink_to_tunnel;
870 static int tun_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
871 int *timeout_io, const struct timeval *tv_now,
877 fds[0].events=POLLIN|POLLERR|POLLHUP;
881 static void tun_afterpoll(void *sst, struct pollfd *fds, int nfds,
882 const struct timeval *tv_now, uint64_t *now)
887 if (fds[0].revents&POLLERR) {
888 printf("tun_afterpoll: hup!\n");
890 if (fds[0].revents&POLLIN) {
891 BUF_ALLOC(st->buff,"tun_afterpoll");
892 buffer_init(st->buff,st->nl.max_start_pad);
893 l=read(st->fd,st->buff->start,st->buff->len-st->nl.max_start_pad);
895 fatal_perror("tun_afterpoll: read()");
898 fatal("tun_afterpoll: read()=0; device gone away?\n");
902 st->netlink_to_tunnel(&st->nl,NULL,st->buff);
903 BUF_ASSERT_FREE(st->buff);
908 static void tun_deliver_to_kernel(void *sst, void *cid,
909 struct buffer_if *buf)
913 BUF_ASSERT_USED(buf);
915 /* No error checking, because we'd just throw the packet away anyway */
916 write(st->fd,buf->start,buf->size);
920 static void tun_phase_hook(void *sst, uint32_t newphase)
923 string_t hostaddr,secnetaddr;
925 string_t network,mask;
926 struct netlink_client *c;
930 if (st->search_for_if) {
934 /* ASSERT st->interface_name */
935 dname=safe_malloc(strlen(st->device_path)+4,"tun_old_apply");
936 st->interface_name=safe_malloc(8,"tun_phase_hook");
938 for (i=0; i<255; i++) {
939 sprintf(dname,"%s%d",st->device_path,i);
940 if ((st->fd=open(dname,O_RDWR))>0) {
941 sprintf(st->interface_name,"tun%d",i);
942 Message(M_INFO,"%s: allocated network interface %s "
943 "through %s\n",st->nl.name,st->interface_name,
949 fatal("%s: unable to open any TUN device (%s...)\n",
950 st->nl.name,st->device_path);
953 st->fd=open(st->device_path,O_RDWR);
955 fatal_perror("%s: unable to open TUN device file %s",
956 st->nl.name,st->device_path);
960 #ifdef HAVE_LINUX_IF_H
963 /* New TUN interface: open the device, then do ioctl TUNSETIFF
964 to set or find out the network interface name. */
965 st->fd=open(st->device_path,O_RDWR);
967 fatal_perror("%s: can't open device file %s",st->nl.name,
970 memset(&ifr,0,sizeof(ifr));
971 ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Just send/receive IP packets,
973 if (st->interface_name)
974 strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ);
975 if (ioctl(st->fd,TUNSETIFF,&ifr)<0) {
976 fatal_perror("%s: ioctl(TUNSETIFF)",st->nl.name);
978 if (!st->interface_name) {
979 st->interface_name=safe_malloc(strlen(ifr.ifr_name)+1,"tun_apply");
980 strcpy(st->interface_name,ifr.ifr_name);
981 Message(M_INFO,"%s: allocated network interface %s\n",st->nl.name,
985 fatal("netlink.c:tun_phase_hook:!tun_old unexpected\n");
986 #endif /* HAVE_LINUX_IF_H */
988 /* All the networks we'll be using have been registered. Invoke ifconfig
989 to set the TUN device's address, and route to add routes to all
992 hostaddr=ipaddr_to_string(st->nl.local_address);
993 secnetaddr=ipaddr_to_string(st->nl.secnet_address);
994 snprintf(mtu,6,"%d",st->nl.mtu);
997 sys_cmd(st->ifconfig_path,"ifconfig",st->interface_name,
998 hostaddr,"netmask","255.255.255.255","-broadcast",
999 "pointopoint",secnetaddr,"mtu",mtu,"up",(char *)0);
1001 for (c=st->nl.clients; c; c=c->next) {
1002 for (i=0; i<c->networks->entries; i++) {
1003 network=ipaddr_to_string(c->networks->list[i].prefix);
1004 mask=ipaddr_to_string(c->networks->list[i].mask);
1005 sys_cmd(st->route_path,"route","add","-net",network,
1006 "netmask",mask,"gw",secnetaddr,(char *)0);
1010 /* Register for poll() */
1011 register_for_poll(st, tun_beforepoll, tun_afterpoll, 1, st->nl.name);
1014 #ifdef HAVE_LINUX_IF_H
1015 static list_t *tun_apply(closure_t *self, struct cloc loc, dict_t *context,
1022 st=safe_malloc(sizeof(*st),"tun_apply");
1024 /* First parameter must be a dict */
1025 item=list_elem(args,0);
1026 if (!item || item->type!=t_dict)
1027 cfgfatal(loc,"tun","parameter must be a dictionary\n");
1029 dict=item->data.dict;
1031 st->netlink_to_tunnel=
1032 netlink_init(&st->nl,st,loc,dict,
1033 "netlink-tun",tun_deliver_to_kernel);
1036 st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
1037 st->interface_name=dict_read_string(dict,"interface",False,
1039 st->ifconfig_path=dict_read_string(dict,"ifconfig-path",
1040 False,"tun-netlink",loc);
1041 st->route_path=dict_read_string(dict,"route-path",
1042 False,"tun-netlink",loc);
1044 if (!st->device_path) st->device_path="/dev/net/tun";
1045 if (!st->ifconfig_path) st->ifconfig_path="ifconfig";
1046 if (!st->route_path) st->route_path="route";
1047 st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"tun-netlink",loc);
1049 add_hook(PHASE_GETRESOURCES,tun_phase_hook,st);
1051 return new_closure(&st->nl.cl);
1053 #endif /* HAVE_LINUX_IF_H */
1055 static list_t *tun_old_apply(closure_t *self, struct cloc loc, dict_t *context,
1062 st=safe_malloc(sizeof(*st),"tun_old_apply");
1064 Message(M_WARNING,"the tun-old code has never been tested. Please report "
1065 "success or failure to steve@greenend.org.uk\n");
1067 /* First parameter must be a dict */
1068 item=list_elem(args,0);
1069 if (!item || item->type!=t_dict)
1070 cfgfatal(loc,"tun","parameter must be a dictionary\n");
1072 dict=item->data.dict;
1074 st->netlink_to_tunnel=
1075 netlink_init(&st->nl,st,loc,dict,
1076 "netlink-tun",tun_deliver_to_kernel);
1079 st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
1080 st->interface_name=dict_read_string(dict,"interface",False,
1082 st->search_for_if=dict_read_bool(dict,"interface-search",False,
1083 "tun-netlink",loc,st->device_path==NULL);
1084 st->ifconfig_path=dict_read_string(dict,"ifconfig-path",False,
1086 st->route_path=dict_read_string(dict,"route-path",False,"tun-netlink",loc);
1088 if (!st->device_path) st->device_path="/dev/tun";
1089 if (!st->ifconfig_path) st->ifconfig_path="ifconfig";
1090 if (!st->route_path) st->route_path="route";
1091 st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"tun-netlink",loc);
1093 /* Old TUN interface: the network interface name depends on which
1094 /dev/tunX file we open. If 'interface-search' is set to true, treat
1095 'device' as the prefix and try numbers from 0--255. If it's set
1096 to false, treat 'device' as the whole name, and require than an
1097 appropriate interface name be specified. */
1098 if (st->search_for_if && st->interface_name) {
1099 cfgfatal(loc,"tun-old","you may not specify an interface name "
1100 "in interface-search mode\n");
1102 if (!st->search_for_if && !st->interface_name) {
1103 cfgfatal(loc,"tun-old","you must specify an interface name "
1104 "when you explicitly specify a TUN device file\n");
1108 add_hook(PHASE_GETRESOURCES,tun_phase_hook,st);
1110 return new_closure(&st->nl.cl);
1113 /* No connection to the kernel at all... */
1119 static void null_deliver(void *sst, void *cid, struct buffer_if *buf)
1124 static list_t *null_apply(closure_t *self, struct cloc loc, dict_t *context,
1131 st=safe_malloc(sizeof(*st),"null_apply");
1133 item=list_elem(args,0);
1134 if (!item || item->type!=t_dict)
1135 cfgfatal(loc,"null-netlink","parameter must be a dictionary\n");
1137 dict=item->data.dict;
1139 netlink_init(&st->nl,st,loc,dict,"null-netlink",null_deliver);
1141 return new_closure(&st->nl.cl);
1144 init_module netlink_module;
1145 void netlink_module(dict_t *dict)
1147 add_closure(dict,"userv-ipif",userv_apply);
1148 #ifdef HAVE_LINUX_IF_H
1149 add_closure(dict,"tun",tun_apply);
1151 add_closure(dict,"tun-old",tun_old_apply);
1152 add_closure(dict,"null-netlink",null_apply);
1155 add_closure(dict,"pty-slip",ptyslip_apply);
1156 add_closure(dict,"slipd",slipd_apply);