📄 vpn.c
字号:
sprintf (ifr.ifr_name, "gnu%d", id); if (ioctl (fd, TUNSETIFF, (void *) &ifr) < 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _ ("Cannot set tunnel name to %s because of %s\n"), ifr.ifr_name, strerror (errno)); id++; used = 1; } else { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("Configured tunnel name to %s\n"), ifr.ifr_name); } } } while (used); ioctl (fd, TUNSETNOCSUM, 1); memcpy (&((store1 + n)->peer), them, sizeof (GNUNET_PeerIdentity)); (store1 + n)->id = id; (store1 + n)->fd = fd; (store1 + n)->active = GNUNET_YES; (store1 + n)->route_entry = 0; /* tun_alloc can change the tunnel name */ /* strncpy((store1+n)->name, ifr.ifr_name,IFNAMSIZ); */ /* here we should give the tunnel an IPv6 address and fake up a route to the other end * the format looks like this, and the net/host split is fixed at /48 as in rfc4193 * local /64 * net: my GNUNET_PeerIdentity * subnet: interface number+2 * interface: NULL * * remote /48 * net: their GNUNET_PeerIdentity * host: NULL (it's not needed for routes) */ /* Run some system commands to set it up... *//* sprintf(cmd, "sudo ifconfig %s up", name); * GNUNET_GE_LOG(ectx, GNUNET_GE_DEBUG | GNUNET_GE_DEVELOPER | GNUNET_GE_REQUEST, _("RFC4193 Calling %s\n"), cmd); * system(cmd); */ /* Bring interface up, like system("sudo ifconfig %s up"); */ /* not needed, we already have the iface name ... strncpy(ifr.ifr_name, name, IFNAMSIZ); */ if (ioctl (admin_fd, SIOCGIFFLAGS, &ifr) < 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("Cannot get socket flags for gnu%d because %s\n"), id, strerror (errno)); } else { ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (ioctl (admin_fd, SIOCSIFFLAGS, &ifr) < 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("Cannot set socket flags for gnu%d because %s\n"), id, strerror (errno)); } } /* Seems to go better with lower mtu, aka system("sudo ifconfig %s mtu 1280") */ ifr.ifr_mtu = 1280; if (ioctl (admin_fd, SIOCSIFMTU, &ifr) < 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("Cannot set MTU for gnu%d because %s\n"), id, strerror (errno)); } /* lets add an IP address... aka "sudo ifconfig %s add %s:%04x::1/64" */ if (ioctl (admin_fd, SIOCGIFINDEX, &ifr) < 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("Cannot get interface index for gnu%d because %s\n"), id, strerror (errno)); } else { /* note to self... htons(64) = kernel oops. */ (store1 + n)->ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = 64; ifr6.ifr6_ifindex = ifr.ifr_ifindex; id2net (&ifr6.ifr6_addr, coreAPI->my_identity); ifr6.ifr6_addr.s6_addr16[3] = htons (n + VC_START); GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_DEVELOPER | GNUNET_GE_REQUEST, _("IPv6 ifaddr gnu%d - %x:%x:%x:%x:%x:%x:%x:%x/%d\n"), id, ntohs (ifr6.ifr6_addr.s6_addr16[0]), ntohs (ifr6.ifr6_addr.s6_addr16[1]), ntohs (ifr6.ifr6_addr.s6_addr16[2]), ntohs (ifr6.ifr6_addr.s6_addr16[3]), ntohs (ifr6.ifr6_addr.s6_addr16[4]), ntohs (ifr6.ifr6_addr.s6_addr16[5]), ntohs (ifr6.ifr6_addr.s6_addr16[6]), ntohs (ifr6.ifr6_addr.s6_addr16[7]), ifr6.ifr6_prefixlen); if (ioctl (admin_fd, SIOCSIFADDR, &ifr6) < 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _ ("Cannot set interface IPv6 address for gnu%d because %s\n"), id, strerror (errno)); } /* lets add a route to the peer, aka "#sudo route -A inet6 add %s::/48 dev %s" */ memset ((char *) &rt, 0, sizeof (struct in6_rtmsg)); /* rtmsg_ifindex would be zero for routes not specifying a device, such as by gateway */ rt.rtmsg_ifindex = ifr.ifr_ifindex; id2net (&rt.rtmsg_dst, them); rt.rtmsg_flags = RTF_UP; rt.rtmsg_metric = 1; /* how many hops to owner of public key */ rt.rtmsg_dst_len = 48; /* network prefix len is 48 by standard */ GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_DEVELOPER | GNUNET_GE_REQUEST, _ ("IPv6 route gnu%d - destination %x:%x:%x:%x:%x:%x:%x:%x/%d\n"), id, ntohs (rt.rtmsg_dst.s6_addr16[0]), ntohs (rt.rtmsg_dst.s6_addr16[1]), ntohs (rt.rtmsg_dst.s6_addr16[2]), ntohs (rt.rtmsg_dst.s6_addr16[3]), ntohs (rt.rtmsg_dst.s6_addr16[4]), ntohs (rt.rtmsg_dst.s6_addr16[5]), ntohs (rt.rtmsg_dst.s6_addr16[6]), ntohs (rt.rtmsg_dst.s6_addr16[7]), rt.rtmsg_dst_len); if (ioctl (admin_fd, SIOCADDRT, &rt) < 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _ ("Cannot add route IPv6 address for gnu%s because %s\n"), id, strerror (errno)); } }}/** * See if we already got a TUN/TAP open for the given GNUnet peer. if not, make one, stick * GNUNET_PeerIdentity and the filehandle and name of the TUN/TAP in an array so we remember we did it. */voidcheckensure_peer (const GNUNET_PeerIdentity * them, void *callerinfo){ int i; tunnel_info *rstore1; int rcapacity1; /* GNUNET_GE_LOG(ectx, GNUNET_GE_DEBUG | GNUNET_GE_DEVELOPER | GNUNET_GE_REQUEST, _("RFC4193 Going to checkensure peer %x then\n"), them->hashPubKey.bits[0]); */ /* first entry in array will be known as gnu0 */ /* if a tunnel is already setup, we don't setup another */ for (i = 0; i < entries1; i++) { if (isEqual (them, &((store1 + i)->peer))) { (store1 + i)->active = GNUNET_YES; return; } } /* * append it at the end. */ entries1++; rcapacity1 = entries1 * sizeof (tunnel_info); if (rcapacity1 > capacity1) { rstore1 = GNUNET_realloc (store1, rcapacity1); if (rstore1 == NULL) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _ ("RFC4193 We have run out of memory and so I can't store a tunnel for this peer.\n")); entries1--; return; } store1 = rstore1; capacity1 = rcapacity1; } /* GNUNET_GE_LOG(ectx, GNUNET_GE_DEBUG | GNUNET_GE_DEVELOPER | GNUNET_GE_REQUEST, _("RFC4193 Extending array for new tunnel\n")); */ setup_tunnel ((entries1 - 1), them);}/* make new thread... * repeat { * call p2p_connections_iterate, create/destroy tunnels to match connected peers, 1 per peer. * Give new tunnels their IPv6 addresses like "ifconfig gnu0 add fdXX:XXXX:XXXX::/48" * SELECT for incoming packets, ciphertext_send those thru gnunet, or (pipe activity = exit this thread) or timeout. * } * own IPv6 addr is fdXX:XXXX:XXXX::P/48 where X= 40 bits own key, P = gnu0 + 2 * route add -net fdXX(remote key) dev gnu0 is then used. */static void *tunThread (void *arg){ fd_set readSet; fd_set errorSet; fd_set writeSet; int i, ret, max; char tmp[MAXSIG_BUF]; struct stat statinfo; /** * IP frames are preceeded by the TUN/TAP header (for Linux) or by the GNUnet header * other systems like HURD, etc may use different headers */ char frame[IP_FRAME + HEADER_FRAME]; struct ip6_hdr *fp; struct tun_pi *tp; GNUNET_MessageHeader *gp; struct timeval timeout; /* need the cast otherwise it increments by HEADER_FRAME * sizeof(frame) rather than HEADER_FRAME */ fp = (struct ip6_hdr *) (((char *) &frame) + HEADER_FRAME); /* this trick decrements the pointer by the sizes of the respective structs */ tp = ((struct tun_pi *) fp) - 1; gp = ((GNUNET_MessageHeader *) fp) - 1; running = 1; GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_DEVELOPER | GNUNET_GE_REQUEST, _ ("RFC4193 Thread running (frame %d tunnel %d f2f %d) ...\n"), fp, tp, gp); GNUNET_mutex_lock (lock); while (running) { FD_ZERO (&readSet); FD_ZERO (&errorSet); FD_ZERO (&writeSet); max = signalingPipe[0]; if (-1 != FSTAT (signalingPipe[0], &statinfo)) { FD_SET (signalingPipe[0], &readSet); } else { GNUNET_GE_DIE_STRERROR (ectx, GNUNET_GE_FATAL | GNUNET_GE_ADMIN | GNUNET_GE_BULK, "fstat"); } for (i = 0; i < entries1; i++) { FD_SET (((store1 + i)->fd), &readSet); max = maxi (max, (store1 + i)->fd); } GNUNET_mutex_unlock (lock); timeout.tv_sec = interval; timeout.tv_usec = 0; ret = SELECT (max + 1, &readSet, &writeSet, &errorSet, &timeout); if (ret < 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, "From the vpn select: %s\n", strerror (errno)); running = 0; break; } if (FD_ISSET (signalingPipe[0], &readSet)) { if (0 >= READ (signalingPipe[0], &tmp[0], MAXSIG_BUF)) GNUNET_GE_LOG_STRERROR (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER, "vpn could not read from exit control pipe\n"); } GNUNET_mutex_lock (lock); for (i = 0; i < entries1; i++) { if (FD_ISSET (((store1 + i)->fd), &readSet)) { ret = read (((store1 + i)->fd), tp, IP_FRAME); /* goodbye IPv6 packet, enjoy the GNUnet... :-) * IP is of course very important so it will enjoy * the very highest priority */ if (valid_incoming (ret, tp, fp)) { gp->type = htons (GNUNET_P2P_PROTO_AIP_IP); gp->size = htons (sizeof (GNUNET_MessageHeader) + ret - sizeof (struct tun_pi)); coreAPI->ciphertext_send (&((store1 + i)->peer), gp, GNUNET_EXTREME_PRIORITY, 1); coreAPI->p2p_connection_preference_increase (& ((store1 + i)->peer), 1000); } } /* we do this here as we get a race if the p2p handler tries it */ if (((store1 + i)->active) == 0) { if (close ((store1 + i)->fd) == 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER, _("VPN dropping connection %x\n"), i); *(store1 + i) = *(store1 + (entries1 - 1)); entries1--; } else { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("VPN cannot drop connection %x\n"), i); } } }/* if (timeout.tv_sec < (interval / 2)) { for (i = 0; i < entries1; i++) { if (((store1+i)->active) > 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -