Date: Fri, 12 Dec 2008 10:20:00 +0200 From: Alexander Motin <mav@mavhome.dp.ua> To: Nikos Vassiliadis <nvass@teledomenet.gr> Cc: freebsd-net@freebsd.org Subject: Re: ng_bridge + ng_ksocket Message-ID: <49421EB0.7040205@mavhome.dp.ua> In-Reply-To: <1229005383.00046904.1228994401@10.7.7.3> References: <1229005383.00046904.1228994401@10.7.7.3>
next in thread | previous in thread | raw e-mail | index | archive | help
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 <config.h> #endif extern "C" { # include <unistd.h> # include <sys/types.h> # include <pthread.h> # include <sys/types.h> # include <sys/socket.h> # include <net/if.h> # include <signal.h> # include <net/ethernet.h> # include <pcap.h> # include <arpa/inet.h> # include <netinet/in.h> # include <netinet/in_systm.h> # include <netinet/ip.h> # include <netinet/udp.h> # include <errno.h> }; #include <iostream> #include <cstdlib> #include <cstring> #include <map> 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<<","<<our_script<<","<<tmp << std::endl; std::cerr << "execl():" << execl(our_script,our_script,tmp,(char *)0 ); std::cerr << " " << errno << std::endl; break; case -1: std::cerr << "Can't fork()!" << std::endl; break; default: break; } } } return 0; } #undef ETHER_MIN_LEN #define ETHER_MIN_LEN 14 void if_ether(u_char *user, const struct pcap_pkthdr *h, register const u_char *buf) { if (!ETHER_IS_VALID_LEN(h->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 " <<std::endl; std::cerr<< " " << ebuf <<std::endl; return 1; } struct bpf_program fcode; bpf_u_int32 netmask=0; int Oflag = 1; char expr[128]; int num; snprintf(expr,128,"udp and dst host %s and dst port %d",our_addr,our_port); /* and compile it */ if (pcap_compile(pd, &fcode, expr, Oflag, netmask) < 0 || pcap_setfilter(pd, &fcode) < 0) { std::cerr << "FIXME!!! bad filter: " << pcap_geterr(pd) << std::endl; pcap_close(pd); return 2; } while (1) { num = pcap_dispatch(pd, -1, if_ether, NULL); }; return 0; } --------------060705090100070300010900--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?49421EB0.7040205>