From owner-freebsd-net@FreeBSD.ORG Fri Dec 12 09:20:04 2008 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 012F11065673 for ; Fri, 12 Dec 2008 09:20:04 +0000 (UTC) (envelope-from mav@mavhome.dp.ua) Received: from cmail.optima.ua (cmail.optima.ua [195.248.191.121]) by mx1.freebsd.org (Postfix) with ESMTP id 2EA628FC12 for ; Fri, 12 Dec 2008 09:20:02 +0000 (UTC) (envelope-from mav@mavhome.dp.ua) X-Spam-Flag: SKIP X-Spam-Yversion: Spamooborona-2.1.0 Received: from orphanage.alkar.net (account mav@alkar.net [212.86.226.11] verified) by cmail.optima.ua (CommuniGate Pro SMTP 5.2.9) with ESMTPA id 229581490; Fri, 12 Dec 2008 10:20:00 +0200 Message-ID: <49421EB0.7040205@mavhome.dp.ua> Date: Fri, 12 Dec 2008 10:20:00 +0200 From: Alexander Motin User-Agent: Thunderbird 2.0.0.14 (X11/20080612) MIME-Version: 1.0 To: Nikos Vassiliadis References: <1229005383.00046904.1228994401@10.7.7.3> In-Reply-To: <1229005383.00046904.1228994401@10.7.7.3> Content-Type: multipart/mixed; boundary="------------060705090100070300010900" Cc: freebsd-net@freebsd.org Subject: Re: ng_bridge + ng_ksocket X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Dec 2008 09:20:04 -0000 This is a multi-part message in MIME format. --------------060705090100070300010900 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Nikos Vassiliadis wrote: > I would like to create an ethernet over UDP tunnel. For my > purposes, using ng_bridge and ng_ksocket seem fine. The > problem is that the peer address/port is not known, since > it will be behind a NAT device and will have a dynamically > assigned IP address. In userspace I would use something like > recvfrom() to get the peer address. I don't know what to do > for ngctl and ng_ksocket. Any suggestions? Is this doable? > Is there something I can do to circumvent the problem? Five years ago I had the same problem. In result, I have written a small program which monitor interface with libpcap and calls script to reconnect ng_ksocket to the new peer address/port when it changes. The code is old, dirty and was not used for a long time, but if you wish to try that way - it is attached. -- Alexander Motin --------------060705090100070300010900 Content-Type: text/plain; name="main.cc" Content-Transfer-Encoding: 8bit Content-Disposition: inline; filename="main.cc" #ifdef HAVE_CONFIG_H #include #endif extern "C" { # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include }; #include #include #include #include extern char *optarg; extern int optind; extern int optopt; extern int opterr; extern int optreset; char our_iface[5]; char our_addr[16]; int our_port; char our_script[128]; unsigned int cur_addr=0; unsigned int cur_port=0; void discard(int sig) { std::cerr << "получен сигнал" << std::endl; } void usage() { std::cout << "program -i iface -a addr -p port -s script" << std::endl; } int if_ip(register const u_char *buf, unsigned int size) { if (size < sizeof(struct ip)) { std::cerr << "it is too small (" << size << " bytes) to be an ip packet." << std::endl; return 1; } struct ip *ip = (struct ip*) buf; if (ip->ip_v != IPVERSION) { std::cerr << "ip ver != " << IPVERSION << ": discard " << size << "bytes" << std::endl; return 2; } if ((ip->ip_p == IPPROTO_UDP)&&((ntohs(ip->ip_off) & IP_OFFMASK) == 0)) { u_int hlen = ip->ip_hl * 4; u_char *cp = (u_char *)ip + hlen; unsigned int addr=ip->ip_src.s_addr; struct in_addr in; in.s_addr=addr; unsigned int port=ntohs(((struct udphdr *)cp)->uh_sport); if ((cur_addr!=addr) || (cur_port!=port)) { std::cerr << "CHANGED to " << inet_ntoa(in)<< ":" << port << std::endl; cur_addr=addr; cur_port=port; switch (fork()) { case 0: char tmp[128]; snprintf(tmp,128,"%s:%d",inet_ntoa(in),port); // std::cerr << our_script<<","<caplen)) { // validate Ether packet length return; } struct ether_header *p = (struct ether_header *)buf; if (ntohs(p->ether_type)==ETHERTYPE_IP) { if_ip(buf+sizeof(struct ether_header), h->caplen-sizeof(struct ether_header)); } return; } int main(int argc, char *argv[]) { int ch; while ((ch = getopt(argc, argv,"i:a:p:s:"))!=-1) { switch (ch) { case 'i': strncpy(our_iface,optarg,5); break; case 'a': strncpy(our_addr,optarg,16); break; case 'p': our_port = atoi(optarg); break; case 's': strncpy(our_script,optarg,128); break; case '?': default: usage(); return 1; } } //------------------------------------------- signal(SIGTERM, discard); siginterrupt(SIGTERM, 1); pcap_t *pd; char ebuf[PCAP_ERRBUF_SIZE]; /* open bpf with required snaplen */ if ((pd = pcap_open_live(our_iface, 100, 0/*no_promisc...*/, 10000, ebuf)) == NULL) { std::cerr<<"ошибка pcap_open_live " <