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