Blocked revisions 580 via svnmerge
[senf.git] / Socket / Protocols / INet / RawINetSocketHandle.test.cc
1 // $Id: RawINetSocketHandle.test.cc 597 2008-01-15 09:16:20Z g0dil $
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS) 
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY 
6 //     David Wagner <dw6@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief RawINetSocketHandle.test unit tests */
25
26 #include <sys/types.h>
27 #include <sys/ioctl.h>
28 #include <sys/wait.h>
29 #include <unistd.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include "RawINetSocketHandle.hh"
33 #include <iostream>
34
35 #include "../../../Utils/auto_unit_test.hh"
36 #include <boost/test/test_tools.hpp>
37
38 namespace {
39
40     void error(char const * fn, char const * proc="")
41     {
42         std::cerr << "\n" << proc << ((*proc)?": ":"") << fn << ": " << strerror(errno) << std::endl;
43     }
44
45     void fail(char const * proc, char const * fn)
46     {
47         error(fn,proc);
48         _exit(1);
49     }
50
51     int server_pid = 0;
52
53     void start(void (*fn)())
54     {
55         server_pid = ::fork();
56         if (server_pid < 0) BOOST_FAIL("fork()");
57         if (server_pid == 0) {
58             (*fn)();
59             _exit(0);
60         }
61     }
62
63     void wait()
64     {
65         int status;
66         if (waitpid(server_pid,&status,0)<0)
67             BOOST_FAIL("waitpid()");
68         BOOST_CHECK_EQUAL( status , 0 );
69     }
70
71     void stop()
72     {
73         if (server_pid) {
74             kill(server_pid,9);
75             wait();
76             server_pid = 0;
77         }
78     }
79
80 }
81
82 ///////////////////////////////////////////////////////////////////////////
83
84 namespace {
85
86     void server_v4() //listen for packets with proto=47 (GRE) and resend them with proto=48
87     {
88         struct sockaddr_in sin;
89         ::memset(&sin,0,sizeof(sin));
90         sin.sin_family = AF_INET;
91         sin.sin_port = htons(0);
92         sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
93         
94         int sockrec = socket(PF_INET,SOCK_RAW,47);
95         if (sockrec<0) fail("server_v4","socket(rec)");
96         int socksend = socket(PF_INET,SOCK_RAW,48);
97         if (socksend<0) fail("server_v4","socket(send)");
98         
99         char buffer[1024];
100         while (1) {
101             int n = read(sockrec,buffer,1024);
102             if (n == 20+4 )//&& strncmp(,"QUIT",4) == 0)
103                 break;
104             sleep(1);
105             //jaja, fieses gehacke...
106             sendto(socksend,buffer+20,n-20,0,(struct sockaddr *)&sin,sizeof(sin));
107         }
108
109         if (close(sockrec) < 0) fail("server_v4","close(rec)");
110         if (close(socksend) < 0) fail("server_v4","close(send)");
111     }
112     void server_v6() //listen for packets with proto=47 (GRE) and resend them with proto=48
113     {
114         struct sockaddr_in6 sin;
115         ::memset(&sin,0,sizeof(sin));
116         sin.sin6_family = AF_INET6;
117         sin.sin6_port = htons(0);
118         inet_pton(AF_INET6, "::1", &sin.sin6_addr);        
119         int sockrec6 = socket(PF_INET6,SOCK_RAW,47);
120         if (sockrec6<0) fail("server_v6","socket(rec)");
121         int socksend6 = socket(PF_INET6,SOCK_RAW,48);
122         if (socksend6<0) fail("server_v6","socket(send)");
123         char buffer[1024];
124         while (1) {
125             int n = read(sockrec6,buffer,1024);
126             if (n<0) fail("server_v6","read(sockrec6)");
127             if (n == 4 && strncmp(buffer,"QUIT",4) == 0)
128                 break;
129             sleep(1);
130             //jaja, fieses gehacke...
131             n = sendto(socksend6,buffer,n,0,(struct sockaddr *)&sin,sizeof(sin));
132             if (n<0) fail("server_v6","sendto(socksend6)");
133         }
134         if (close(sockrec6) < 0) fail("server_v6","close(rec)");
135         if (close(socksend6) < 0) fail("server_v6","close(send)");
136     }
137
138 }
139
140 BOOST_AUTO_UNIT_TEST(RawV4ClientSocketHandle)
141 {
142     if (getuid() != 0) {
143         BOOST_WARN_MESSAGE(false, "Cannot test senf::RawV4SocketHandle as non-root user");
144         return;
145     }
146     try {
147         std::string test = "TEST-WRITE";
148         alarm(10);
149         start(server_v4);
150         senf::RawV4ClientSocketHandle sock(47);  //IPPROTO_GRE
151         BOOST_CHECK_NO_THROW( sock.protocol().rcvbuf(2048) );
152         BOOST_CHECK_EQUAL( sock.protocol().rcvbuf(), 2048u );
153         BOOST_CHECK_NO_THROW( sock.protocol().sndbuf(2048) );
154         BOOST_CHECK_EQUAL( sock.protocol().sndbuf(), 2048u );
155         BOOST_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"), test) );
156                 senf::RawV4ClientSocketHandle sockrec(48);  //IPPROTO_GRE+1
157                 std::string in = sockrec.read();
158                 BOOST_CHECK_EQUAL(in.substr(20), test); 
159         BOOST_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"),"QUIT"));
160         //sock.close();
161         //sockrec.close();
162         alarm(0);
163     } catch (...) {
164         alarm(0);
165         throw;
166     }
167 }
168
169 BOOST_AUTO_UNIT_TEST(RawV6ClientSocketHandle)
170 {
171     if (getuid() != 0) {
172         BOOST_WARN_MESSAGE(false, "Cannot test senf::RawV6SocketHandle as non-root user");
173         return;
174     }
175     try {
176         std::string test = "TEST-WRITE";
177         alarm(5);
178         start(server_v6);
179         sleep(1);
180         senf::RawV6ClientSocketHandle sock(47);  //IPPROTO_GRE
181         BOOST_CHECK_NO_THROW( sock.protocol().rcvbuf(2048) );
182         BOOST_CHECK_EQUAL( sock.protocol().rcvbuf(), 2048u );
183         BOOST_CHECK_NO_THROW( sock.protocol().sndbuf(2048) );
184         BOOST_CHECK_EQUAL( sock.protocol().sndbuf(), 2048u );
185         BOOST_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"), test) );
186                 senf::RawV6ClientSocketHandle sockrec(48);  //IPPROTO_GRE+1
187                 std::string in = sockrec.read();
188                 BOOST_CHECK_EQUAL(in, test); 
189         BOOST_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"),"QUIT"));
190         alarm(0);
191     } catch (...) {
192         alarm(0);
193         throw;
194     }
195 }
196
197 ///////////////////////////////cc.e////////////////////////////////////////
198 #undef prefix_
199
200 \f
201 // Local Variables:
202 // mode: c++
203 // fill-column: 100
204 // comment-column: 40
205 // c-file-style: "senf"
206 // indent-tabs-mode: nil
207 // ispell-local-dictionary: "american"
208 // compile-command: "scons -u test"
209 // End: