2526f54ff569cb5c04009a13c7d1599fed4ed52e
[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 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   David Wagner <dw6@berlios.de>
27 /** \file
28     \brief RawINetSocketHandle unit tests */
29
30 #include <sys/types.h>
31 #include <sys/ioctl.h>
32 #include <sys/wait.h>
33 #include <unistd.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include "RawINetSocketHandle.hh"
37 #include <iostream>
38
39 #include <senf/Utils/auto_unit_test.hh>
40 #include <boost/test/test_tools.hpp>
41
42 namespace {
43
44     void error(char const * fn, char const * proc="")
45     {
46         std::cerr << "\n" << proc << ((*proc)?": ":"") << fn << ": " << strerror(errno) << std::endl;
47     }
48
49     void fail(char const * proc, char const * fn)
50     {
51         error(fn,proc);
52         _exit(1);
53     }
54
55     int server_pid = 0;
56
57     void start(void (*fn)())
58     {
59         server_pid = ::fork();
60         if (server_pid < 0) BOOST_FAIL("fork()");
61         if (server_pid == 0) {
62             (*fn)();
63             _exit(0);
64         }
65     }
66
67     void wait()
68     {
69         int status;
70         if (waitpid(server_pid,&status,0)<0)
71             BOOST_FAIL("waitpid()");
72         BOOST_CHECK_EQUAL( status , 0 );
73     }
74
75     void stop()
76     {
77         if (server_pid) {
78             kill(server_pid,9);
79             wait();
80             server_pid = 0;
81         }
82     }
83
84 }
85
86 //-/////////////////////////////////////////////////////////////////////////////////////////////////
87
88 namespace {
89
90     void server_v4() //listen for packets with proto=47 (GRE) and resend them with proto=48
91     {
92         struct sockaddr_in sin;
93         ::memset(&sin,0,sizeof(sin));
94         sin.sin_family = AF_INET;
95         sin.sin_port = htons(0);
96         sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
97
98         int sockrec = socket(PF_INET,SOCK_RAW,47);
99         if (sockrec<0) fail("server_v4","socket(rec)");
100         int socksend = socket(PF_INET,SOCK_RAW,48);
101         if (socksend<0) fail("server_v4","socket(send)");
102
103         char buffer[1024];
104         while (1) {
105             int n = read(sockrec,buffer,1024);
106             if (n == 20+4 )//&& strncmp(,"QUIT",4) == 0)
107                 break;
108             sleep(1);
109             //jaja, fieses gehacke...
110             sendto(socksend,buffer+20,n-20,0,(struct sockaddr *)&sin,sizeof(sin));
111         }
112
113         if (close(sockrec) < 0) fail("server_v4","close(rec)");
114         if (close(socksend) < 0) fail("server_v4","close(send)");
115     }
116     void server_v6() //listen for packets with proto=47 (GRE) and resend them with proto=48
117     {
118         struct sockaddr_in6 sin;
119         ::memset(&sin,0,sizeof(sin));
120         sin.sin6_family = AF_INET6;
121         sin.sin6_port = htons(0);
122         inet_pton(AF_INET6, "::1", &sin.sin6_addr);
123         int sockrec6 = socket(PF_INET6,SOCK_RAW,47);
124         if (sockrec6<0) fail("server_v6","socket(rec)");
125         int socksend6 = socket(PF_INET6,SOCK_RAW,48);
126         if (socksend6<0) fail("server_v6","socket(send)");
127         char buffer[1024];
128         while (1) {
129             int n = read(sockrec6,buffer,1024);
130             if (n<0) fail("server_v6","read(sockrec6)");
131             if (n == 4 && strncmp(buffer,"QUIT",4) == 0)
132                 break;
133             sleep(1);
134             //jaja, fieses gehacke...
135             n = sendto(socksend6,buffer,n,0,(struct sockaddr *)&sin,sizeof(sin));
136             if (n<0) fail("server_v6","sendto(socksend6)");
137         }
138         if (close(sockrec6) < 0) fail("server_v6","close(rec)");
139         if (close(socksend6) < 0) fail("server_v6","close(send)");
140     }
141
142 }
143
144 SENF_AUTO_UNIT_TEST(RawV4ClientSocketHandle)
145 {
146     if (getuid() != 0) {
147         BOOST_WARN_MESSAGE(false, "Cannot test senf::RawV4SocketHandle as non-root user");
148         BOOST_CHECK( true );
149         return;
150     }
151     try {
152         std::string test = "TEST-WRITE";
153         alarm(10);
154         start(server_v4);
155         senf::RawV4ClientSocketHandle sock(47);  //IPPROTO_GRE
156         SENF_CHECK_NO_THROW( sock.protocol().rcvbuf(2048) );
157         BOOST_CHECK_EQUAL( sock.protocol().rcvbuf(), 2048u );
158         SENF_CHECK_NO_THROW( sock.protocol().sndbuf(2048) );
159         BOOST_CHECK_EQUAL( sock.protocol().sndbuf(), 2048u );
160         SENF_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"), test) );
161         senf::RawV4ClientSocketHandle sockrec(48);  //IPPROTO_GRE+1
162         std::string in = sockrec.read();
163         BOOST_CHECK_EQUAL(in.substr(20), test);
164         SENF_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"),"QUIT"));
165         //sock.close();
166         //sockrec.close();
167         alarm(0);
168     } catch (...) {
169         alarm(0);
170         throw;
171     }
172 }
173
174 SENF_AUTO_UNIT_TEST(RawV6ClientSocketHandle)
175 {
176     if (getuid() != 0) {
177         BOOST_WARN_MESSAGE(false, "Cannot test senf::RawV6SocketHandle as non-root user");
178         BOOST_CHECK( true );
179         return;
180     }
181     try {
182         std::string test = "TEST-WRITE";
183         alarm(5);
184         start(server_v6);
185         sleep(1);
186         senf::RawV6ClientSocketHandle sock(47);  //IPPROTO_GRE
187         SENF_CHECK_NO_THROW( sock.protocol().rcvbuf(2048) );
188         BOOST_CHECK_EQUAL( sock.protocol().rcvbuf(), 2048u );
189         SENF_CHECK_NO_THROW( sock.protocol().sndbuf(2048) );
190         BOOST_CHECK_EQUAL( sock.protocol().sndbuf(), 2048u );
191         SENF_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"), test) );
192         senf::RawV6ClientSocketHandle sockrec(48);  //IPPROTO_GRE+1
193         std::string in = sockrec.read();
194         BOOST_CHECK_EQUAL(in, test);
195         SENF_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"),"QUIT"));
196         alarm(0);
197     } catch (...) {
198         alarm(0);
199         throw;
200     }
201 }
202
203 //-/////////////////////////////////////////////////////////////////////////////////////////////////
204 #undef prefix_
205
206 \f
207 // Local Variables:
208 // mode: c++
209 // fill-column: 100
210 // comment-column: 40
211 // c-file-style: "senf"
212 // indent-tabs-mode: nil
213 // ispell-local-dictionary: "american"
214 // compile-command: "scons -u test"
215 // End: