3f5b1c01677cc3628675e7dfc9731857049e03d9
[senf.git] / senf / Socket / Protocols / Raw / PacketSocketHandle.cc
1 // $Id$
2 //
3 // Copyright (C) 2006
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 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief PacketSocketProtocol and PacketSocketHandle non-inline non-template implementation
30  */
31
32 #include "PacketSocketHandle.hh"
33 //#include "PacketSocketHandle.ih"
34
35 // Custom includes
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <netpacket/packet.h>
39 #include <net/ethernet.h>
40 #include <netinet/in.h>
41 #include <net/if.h>
42 #include <errno.h>
43
44 //#include "PacketSocketHandle.mpp"
45 #define prefix_
46 //-/////////////////////////////////////////////////////////////////////////////////////////////////
47
48 prefix_ void senf::PacketSocketProtocol::init_client(SocketType type, int protocol)
49     const
50 {
51     int socktype = SOCK_RAW;
52     if (type == DatagramSocket)
53         socktype = SOCK_DGRAM;
54     if (protocol == -1)
55         protocol = ETH_P_ALL;
56     int sock = ::socket(PF_PACKET, socktype, htons(protocol));
57     if (sock < 0)
58         SENF_THROW_SYSTEM_EXCEPTION("::socket(...) failed.");
59     fd(sock);
60 }
61
62 prefix_ unsigned senf::PacketSocketProtocol::available()
63     const
64 {
65     if (! fh().readable())
66         return 0;
67     ssize_t l = ::recv(fd(),0,0,MSG_PEEK | MSG_TRUNC);
68     if (l < 0)
69         SENF_THROW_SYSTEM_EXCEPTION("::recv(socket_fd) failed.");
70     return l;
71 }
72
73 prefix_ bool senf::PacketSocketProtocol::eof()
74     const
75 {
76     return false;
77 }
78
79 namespace {
80
81     void do_mc(int fd, std::string const & interface, senf::MACAddress address, bool add)
82     {
83         struct packet_mreq mreq;
84         ::memset(&mreq, 0, sizeof(mreq));
85         mreq.mr_ifindex = ::if_nametoindex(interface.c_str());
86         if (mreq.mr_ifindex == 0)
87             throw senf::SystemException(EINVAL);
88         mreq.mr_type = PACKET_MR_MULTICAST;
89         mreq.mr_alen = 6;
90         std::copy(address.begin(), address.end(), &mreq.mr_address[0]);
91         if (::setsockopt(fd, SOL_PACKET,
92                         add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
93                         &mreq, sizeof(mreq)) < 0)
94             throw senf::SystemException();
95     }
96 }
97
98 prefix_ void senf::PacketSocketProtocol::mcAdd(std::string const & interface,
99                                          MACAddress const & address)
100     const
101 {
102     do_mc(fd(), interface, address, true);
103 }
104
105 prefix_ void senf::PacketSocketProtocol::mcDrop(std::string const & interface,
106                                           MACAddress const & address)
107     const
108 {
109     do_mc(fd(), interface, address, false);
110 }
111
112 prefix_ void senf::PacketSocketProtocol::promisc(std::string const & interface, bool mode)
113     const
114 {
115     struct packet_mreq mreq;
116     ::memset(&mreq, 0, sizeof(mreq));
117     mreq.mr_ifindex = ::if_nametoindex(interface.c_str());
118     if (mreq.mr_ifindex == 0)
119         throw senf::SystemException(EINVAL);
120     mreq.mr_type = PACKET_MR_PROMISC;
121     if (::setsockopt(fd(), SOL_PACKET,
122                      mode ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
123                      &mreq, sizeof(mreq)) < 0)
124         throw senf::SystemException();
125 }
126
127 //-/////////////////////////////////////////////////////////////////////////////////////////////////
128 #undef prefix_
129 //#include "PacketSocketHandle.mpp"
130
131 \f
132 // Local Variables:
133 // mode: c++
134 // fill-column: 100
135 // c-file-style: "senf"
136 // indent-tabs-mode: nil
137 // ispell-local-dictionary: "american"
138 // compile-command: "scons -u test"
139 // comment-column: 40
140 // End: