ccafb81a394e1e0339590a67080aa5a96fec673b
[senf.git] / senf / 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 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 <senf/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 SENF_AUTO_UNIT_TEST(RawV4ClientSocketHandle)
141 {
142     if (getuid() != 0) {
143         BOOST_WARN_MESSAGE(false, "Cannot test senf::RawV4SocketHandle as non-root user");
144         BOOST_CHECK( true );
145         return;
146     }
147     try {
148         std::string test = "TEST-WRITE";
149         alarm(10);
150         start(server_v4);
151         senf::RawV4ClientSocketHandle sock(47);  //IPPROTO_GRE
152         SENF_CHECK_NO_THROW( sock.protocol().rcvbuf(2048) );
153         BOOST_CHECK_EQUAL( sock.protocol().rcvbuf(), 2048u );
154         SENF_CHECK_NO_THROW( sock.protocol().sndbuf(2048) );
155         BOOST_CHECK_EQUAL( sock.protocol().sndbuf(), 2048u );
156         SENF_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"), test) );
157         senf::RawV4ClientSocketHandle sockrec(48);  //IPPROTO_GRE+1
158         std::string in = sockrec.read();
159         BOOST_CHECK_EQUAL(in.substr(20), test);
160         SENF_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"),"QUIT"));
161         //sock.close();
162         //sockrec.close();
163         alarm(0);
164     } catch (...) {
165         alarm(0);
166         throw;
167     }
168 }
169
170 SENF_AUTO_UNIT_TEST(RawV6ClientSocketHandle)
171 {
172     if (getuid() != 0) {
173         BOOST_WARN_MESSAGE(false, "Cannot test senf::RawV6SocketHandle as non-root user");
174         BOOST_CHECK( true );
175         return;
176     }
177     try {
178         std::string test = "TEST-WRITE";
179         alarm(5);
180         start(server_v6);
181         sleep(1);
182         senf::RawV6ClientSocketHandle sock(47);  //IPPROTO_GRE
183         SENF_CHECK_NO_THROW( sock.protocol().rcvbuf(2048) );
184         BOOST_CHECK_EQUAL( sock.protocol().rcvbuf(), 2048u );
185         SENF_CHECK_NO_THROW( sock.protocol().sndbuf(2048) );
186         BOOST_CHECK_EQUAL( sock.protocol().sndbuf(), 2048u );
187         SENF_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"), test) );
188         senf::RawV6ClientSocketHandle sockrec(48);  //IPPROTO_GRE+1
189         std::string in = sockrec.read();
190         BOOST_CHECK_EQUAL(in, test);
191         SENF_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"),"QUIT"));
192         alarm(0);
193     } catch (...) {
194         alarm(0);
195         throw;
196     }
197 }
198
199 ///////////////////////////////cc.e////////////////////////////////////////
200 #undef prefix_
201
202 \f
203 // Local Variables:
204 // mode: c++
205 // fill-column: 100
206 // comment-column: 40
207 // c-file-style: "senf"
208 // indent-tabs-mode: nil
209 // ispell-local-dictionary: "american"
210 // compile-command: "scons -u test"
211 // End: