modules/up/src/Core/network/Network.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- netReadHandler
- Interface
- Interface
- Network
- Network
- dump
- receive
- cksum
1 //
2 // $Id: Network.cc,v 1.1.1.1 2000/03/10 16:32:19 engin Exp $
3 //
4 // Author(s): Ramesh Govindan
5
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9
10 #include <cerrno>
11
12 extern "C" {
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <net/if.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <sys/ioctl.h>
19 };
20
21 #include "util/Types.hh"
22 #include "util/Trail.hh"
23 #include "util/Handler.hh"
24 #include "util/Buffer.hh"
25 #include "sys/File.hh"
26 #include "sys/Pipe.hh"
27 #include "sched/Job.hh"
28 #include "sched/Dispatcher.hh"
29
30 #include "network/Ping.hh"
31 #include "network/Prefix.hh"
32 #include "network/Mtrace.hh"
33 #include "network/Network.hh"
34 #include "network/Headers.hh"
35
36 // Constants
37 static const int MaxBufferSize = 1024;
38 static const int MaxInterfaces = 32;
39
40 // File local
41 static TraceCode traceNetwork("network");
42
43 // Globals
44 Network* network = NULL;
45
46 static void
47 netReadHandler(void* ptr,
/* [<][>][^][v][top][bottom][index][help] */
48 void* arg)
49 {
50 ((Network*) ptr)->receive((RawSocket*) arg);
51 }
52
53 Network::Interface::Interface(char* ifname,
/* [<][>][^][v][top][bottom][index][help] */
54 U32 ifaddr)
55 : ListNode()
56 {
57 name = strdup(ifname);
58 address.set(ifaddr);
59 TRACE(traceNetwork, "adding interface %s:%s\n", name, address.name());
60 }
61
62 Network::Interface::~Interface()
/* [<][>][^][v][top][bottom][index][help] */
63 {
64 TRACE(traceNetwork, "deleting interface %s:%s\n", name, address.name());
65 free(name);
66 }
67
68 Network::Network()
/* [<][>][^][v][top][bottom][index][help] */
69 {
70 Handler rh(netReadHandler, this);
71 Handler nh(NULL, NULL);
72 struct sockaddr_in sin;
73 int socklen = sizeof(sin);
74 int sock;
75 struct ifconf ifc;
76 struct ifreq ifrs[MaxInterfaces];
77 struct ifreq *ifr;
78 Network::Interface* interface;
79 U32 addr;
80 Address group;
81
82 icmpSocket = new RawSocket(rh, nh, RawSocketICMP);
83 igmpSocket = new RawSocket(rh, nh, RawSocketIGMP);
84
85 group.set(MtraceMulticast);
86 igmpSocket->join(group);
87 recvBuffer = new Buffer(MaxBufferSize);
88
89 // First find all interfaces
90 if ((sock = ::socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
91 FATAL("couldn't open socket for getting interfaces: %s\n",
92 strerror(errno));
93 // NotReached
94 }
95
96 ifc.ifc_len = sizeof(struct ifreq) * MaxInterfaces;
97 ifc.ifc_buf = (char*) &(ifrs[0]);
98
99 if (ioctl(sock, SIOCGIFCONF, (void*) &ifc) < 0) {
100 FATAL("failed ioctl for getting interface list: %s\n",
101 strerror(errno));
102 // NotReached
103 }
104
105 for (int i = 0; i < ifc.ifc_len; i++) {
106 ifr = &(ifrs[i]);
107 addr = ntohl(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
108 if (addr == 0) {
109 break;
110 }
111 if (addr != INADDR_LOOPBACK) {
112 interface = new Network::Interface(ifr->ifr_name, addr);
113 interfaces.append(interface);
114 }
115 }
116 close(sock);
117
118 if (interfaces.isEmpty()) {
119 FATAL("couldn't find any usable interfaces\n");
120 // NotReached
121 }
122
123 tprobesSent = 0;
124 tprobesTimedOut = 0;
125 icmprobesSent = 0;
126 icmprobesTimedOut = 0;
127
128 return;
129 }
130
131 Network::~Network()
/* [<][>][^][v][top][bottom][index][help] */
132 {
133 delete icmpSocket;
134 delete igmpSocket;
135 delete recvBuffer;
136 interfaces.clear();
137 pendingPings.clear();
138 pendingTProbes.clear();
139 pendingICMProbes.clear();
140 }
141
142 void
143 Network::dump(FILE* fp)
/* [<][>][^][v][top][bottom][index][help] */
144 {
145 fprintf(fp, "tprobes sent %Lu timed-out %Lu\n",
146 tprobesSent, tprobesTimedOut);
147 fprintf(fp, "icmprobes sent %Lu timed-out %Lu\n",
148 icmprobesSent, icmprobesTimedOut);
149 return;
150 }
151
152 void
153 Network::receive(RawSocket* socket)
/* [<][>][^][v][top][bottom][index][help] */
154 {
155 int length;
156 IP* ip;
157 ICMP* icmp;
158 IGMP* igmp;
159 U16 sum;
160
161 length = socket->read(recvBuffer->contents, recvBuffer->capacity);
162 if (length < 0) {
163 return;
164 }
165 ip = (IP*) recvBuffer->contents;
166 ip->ntoh();
167
168 if (ip->totalLength != length) {
169 return;
170 }
171
172 if (length < (ip->headerLength << 2)) {
173 return;
174 }
175 length -= ip->headerLength << 2;
176
177 switch (ip->protocol) {
178 case IPPROTO_ICMP:
179 {
180 // Sanity check ICMP packet
181 if (length < sizeof(ICMP)) {
182 return;
183 }
184
185 icmp = (ICMP*) ((char*) ip + (ip->headerLength << 2));
186 sum = icmp->checksum;
187 icmp->checksum = 0;
188 if (sum && (sum != network->cksum((U16*) icmp, length))) {
189 return;
190 }
191 icmp->ntoh();
192
193 // Farm out packet to whoever's waiting
194 for (Ping* ping = pendingPings.head(); ping != NULL;
195 ping = pendingPings.next(ping)) {
196 if (ping->receive(ip)) {
197 break;
198 }
199 }
200 for (TProbe* tp = pendingTProbes.head(); tp != NULL;
201 tp = pendingTProbes.next(tp)) {
202 if (tp->receive(ip)) {
203 break;
204 }
205 }
206 for (ICMProbe* tp = pendingICMProbes.head(); tp != NULL;
207 tp = pendingICMProbes.next(tp)) {
208 if (tp->receive(ip)) {
209 break;
210 }
211 }
212 break;
213 }
214
215 case IPPROTO_IGMP:
216 {
217 // Sanity check IGMP packet
218 if (length < sizeof(IGMP)) {
219 return;
220 }
221
222 igmp = (IGMP*) ((char*) ip + (ip->headerLength << 2));
223 sum = igmp->checksum;
224 igmp->checksum = 0;
225 if (sum && (sum != network->cksum((U16*) igmp, length))) {
226 return;
227 }
228 igmp->ntoh();
229 length-= sizeof(IGMP);
230 if (igmp->type != IGMPMtraceResp)
231 return;
232 if (length < sizeof(IGMPTrace)) {
233 TRACE(traceNetwork, "receive: IGMPMtraceResp from is too short\n");
234 return;
235 }
236 IGMPTrace *trace = (IGMPTrace*) (igmp + 1);
237 trace->ntoh();
238 length -= sizeof(IGMPTrace);
239
240 Mtrace* mt = pendingMtraces.head();
241 while (mt != NULL) {
242 Mtrace* nextMt = pendingMtraces.next(mt);
243 if (mt->accept_trace(trace))
244 mt->receive(trace, length);
245 mt = nextMt;
246 }
247 break;
248 }
249
250 default:
251 return;
252 }
253 return;
254 }
255
256 U16
257 Network::cksum(const U16* addr,
/* [<][>][^][v][top][bottom][index][help] */
258 int len)
259 {
260 int nleft = len;
261 const u_short *w = addr;
262 u_short answer;
263 u_short odd_byte = 0;
264 register int sum = 0;
265
266 /*
267 * Our algorithm is simple, using a 32 bit accumulator (sum),
268 * we add sequential 16 bit words to it, and at the end, fold
269 * back all the carry bits from the top 16 bits into the lower
270 * 16 bits.
271 */
272 while( nleft > 1 ) {
273 sum += *w++;
274 nleft -= 2;
275 }
276
277 /* mop up an odd byte, if necessary */
278 if( nleft == 1 ) {
279 *(u_char *)(&odd_byte) = *(u_char *)w;
280 sum += odd_byte;
281 }
282
283 /*
284 * add back carry outs from top 16 bits to low 16 bits
285 */
286 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
287 sum += (sum >> 16); /* add carry */
288 answer = ~sum; /* truncate to 16 bits */
289 return (answer);
290 }
291
292
293 // Copyright (c) 1994 by the University of Southern California.
294 // All rights reserved.
295 //
296 // Permission to use, copy, modify, and distribute this software and
297 // its documentation in source and binary forms for lawful
298 // non-commercial purposes and without fee is hereby granted, provided
299 // that the above copyright notice appear in all copies and that both
300 // the copyright notice and this permission notice appear in supporting
301 // documentation, and that any documentation, advertising materials,
302 // and other materials related to such distribution and use acknowledge
303 // that the software was developed by the University of Southern
304 // California and/or Information Sciences Institute.
305 // The name of the University of Southern California may not
306 // be used to endorse or promote products derived from this software
307 // without specific prior written permission.
308 //
309 // THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
310 // ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
311 // PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
312 // INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
313 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
314 // NON-INFRINGEMENT.
315 //
316 // IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
317 // SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
318 // TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
319 // THE USE OR PERFORMANCE OF THIS SOFTWARE.
320 //
321 // Questions concerning this software should be directed to
322 // scan@isi.edu.
323 //
324
325