00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef lint
00036 static const char rcsid[] =
00037 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/emulate/net-ip.cc,v 1.20 2003/10/12 21:13:09 xuanc Exp $ (LBL)";
00038 #endif
00039
00040 #include <stdio.h>
00041 #ifndef WIN32
00042 #include <unistd.h>
00043 #endif
00044 #include <time.h>
00045 #include <errno.h>
00046 #include <string.h>
00047 #ifdef WIN32
00048 #include <io.h>
00049 #define close closesocket
00050 #else
00051 #include <sys/param.h>
00052 #include <sys/socket.h>
00053 #include <sys/ioctl.h>
00054 #include <netinet/in.h>
00055 #include <netinet/in_systm.h>
00056 #include <netinet/ip.h>
00057 typedef int Socket;
00058 #endif
00059 #if defined(sun) && defined(__svr4__)
00060 #include <sys/systeminfo.h>
00061 #endif
00062
00063 #include "config.h"
00064 #include "net.h"
00065 #include "inet.h"
00066 #include "tclcl.h"
00067 #include "scheduler.h"
00068
00069
00070 #ifdef NIPDEBUG
00071 #define NIDEBUG(x) { if (NIPDEBUG) fprintf(stderr, (x)); }
00072 #define NIDEBUG2(x,y) { if (NIPDEBUG) fprintf(stderr, (x), (y)); }
00073 #define NIDEBUG3(x,y,z) { if (NIPDEBUG) fprintf(stderr, (x), (y), (z)); }
00074 #define NIDEBUG4(w,x,y,z) { if (NIPDEBUG) fprintf(stderr, (w), (x), (y), (z)); }
00075 #define NIDEBUG5(v,w,x,y,z) { if (NIPDEBUG) fprintf(stderr, (v), (w), (x), (y), (z)); }
00076 #else
00077 #define NIDEBUG(x) { }
00078 #define NIDEBUG2(x,y) { }
00079 #define NIDEBUG3(x,y,z) { }
00080 #define NIDEBUG4(w,x,y,z) { }
00081 #define NIDEBUG5(v,w,x,y,z) { }
00082 #endif
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 class IPNetwork : public Network {
00097 public:
00098 IPNetwork();
00099
00100 inline int ttl() const { return (mttl_); }
00101 inline int noloopback_broken() {
00102 return (noloopback_broken_);
00103 }
00104 int setmttl(Socket, int);
00105 int setmloop(Socket, int);
00106 int command(int argc, const char*const* argv);
00107 inline Socket rchannel() { return(rsock_); }
00108 inline Socket schannel() { return(ssock_); }
00109
00110 int send(u_char* buf, int len);
00111 int recv(u_char* buf, int len, sockaddr& from, double& );
00112
00113 inline in_addr& laddr() { return (localaddr_); }
00114 inline in_addr& dstaddr() { return (destaddr_); }
00115
00116 int add_membership(Socket, in_addr& grp);
00117 int drop_membership(Socket, in_addr& grp);
00118
00119
00120
00121 static int bindsock(Socket, in_addr&, u_int16_t, sockaddr_in&);
00122 static int connectsock(Socket, in_addr&, u_int16_t, sockaddr_in&);
00123 static int rbufsize(Socket, int);
00124 static int sbufsize(Socket, int);
00125
00126 protected:
00127 in_addr destaddr_;
00128 in_addr localaddr_;
00129 int mttl_;
00130 Socket rsock_;
00131 Socket ssock_;
00132 int noloopback_broken_;
00133 int loop_;
00134
00135
00136 void reset(int reconfigure);
00137 virtual int open(int mode);
00138 virtual void reconfigure();
00139 int close();
00140
00141 time_t last_reset_;
00142 };
00143
00144 class UDPIPNetwork : public IPNetwork {
00145 public:
00146 UDPIPNetwork();
00147
00148 int send(u_char*, int);
00149 int recv(u_char*, int, sockaddr&, double&);
00150 int open(int mode);
00151
00152 int command(int argc, const char*const* argv);
00153 void reconfigure();
00154 void add_membership(Socket, in_addr&, u_int16_t);
00155 protected:
00156 int bind(in_addr&, u_int16_t port);
00157 int connect(in_addr& remoteaddr, u_int16_t port);
00158 u_int16_t lport_;
00159 u_int16_t port_;
00160 };
00161
00162 static class IPNetworkClass : public TclClass {
00163 public:
00164 IPNetworkClass() : TclClass("Network/IP") {}
00165 TclObject* create(int, const char*const*) {
00166 return (new IPNetwork);
00167 }
00168 } nm_ip;
00169
00170 static class UDPIPNetworkClass : public TclClass {
00171 public:
00172 UDPIPNetworkClass() : TclClass("Network/IP/UDP") {}
00173 TclObject* create(int, const char*const*) {
00174 return (new UDPIPNetwork);
00175 }
00176 } nm_ip_udp;
00177
00178 IPNetwork::IPNetwork() :
00179 mttl_(0),
00180 rsock_(-1),
00181 ssock_(-1),
00182 noloopback_broken_(0),
00183 loop_(1)
00184 {
00185 localaddr_.s_addr = 0L;
00186 destaddr_.s_addr = 0L;
00187 NIDEBUG("IPNetwork: ctor\n");
00188 }
00189
00190 UDPIPNetwork::UDPIPNetwork() :
00191 lport_(htons(0)),
00192 port_(htons(0))
00193 {
00194 NIDEBUG("UDPIPNetwork: ctor\n");
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 int
00204 UDPIPNetwork::send(u_char* buf, int len)
00205 {
00206 int cc = ::send(schannel(), (char*)buf, len, 0);
00207 NIDEBUG5("UDPIPNetwork(%s): ::send(%d, buf, %d) returned %d\n",
00208 name(), schannel(), len, cc);
00209
00210 if (cc < 0) {
00211 switch (errno) {
00212 case ECONNREFUSED:
00213
00214 #if defined(__osf__) || defined(_AIX) || defined(__FreeBSD__)
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 reset(1);
00252 #endif
00253 break;
00254
00255 case ENETUNREACH:
00256 case EHOSTUNREACH:
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 cc = ::send(schannel(), (char*)buf, len, 0);
00268 break;
00269
00270 default:
00271 fprintf(stderr, "UDPIPNetwork(%s): send failed: %s\n",
00272 name(), strerror(errno));
00273 return (-1);
00274 }
00275 }
00276 return cc;
00277 }
00278 int
00279 UDPIPNetwork::recv(u_char* buf, int len, sockaddr& from, double& ts)
00280 {
00281 sockaddr_in sfrom;
00282 int fromlen = sizeof(sfrom);
00283 int cc = ::recvfrom(rsock_, (char*)buf, len, 0,
00284 (sockaddr*)&sfrom, (socklen_t*)&fromlen);
00285 NIDEBUG5("UDPIPNetwork(%s): ::recvfrom(%d, buf, %d) returned %d\n",
00286 name(), rsock_, len, cc);
00287 if (cc < 0) {
00288 if (errno != EWOULDBLOCK) {
00289 fprintf(stderr,
00290 "UDPIPNetwork(%s): recvfrom failed: %s\n",
00291 name(), strerror(errno));
00292 }
00293 return (-1);
00294 }
00295 from = *((sockaddr*)&sfrom);
00296
00297
00298
00299
00300
00301
00302
00303
00304 if (!loop_ && noloopback_broken_ &&
00305 sfrom.sin_addr.s_addr == localaddr_.s_addr &&
00306 sfrom.sin_port == lport_) {
00307 NIDEBUG2("UDPIPNetwork(%s): filtered out our own pkt\n", name());
00308 return (0);
00309 }
00310
00311 ts = Scheduler::instance().clock();
00312 return (cc);
00313 }
00314
00315 int
00316 UDPIPNetwork::open(int mode)
00317 {
00318 if (mode == O_RDONLY || mode == O_RDWR) {
00319 rsock_ = socket(AF_INET, SOCK_DGRAM, 0);
00320 if (rsock_ < 0) {
00321 fprintf(stderr,
00322 "UDPIPNetwork(%s): open: couldn't open rcv sock\n",
00323 name());
00324 }
00325 nonblock(rsock_);
00326 int on = 1;
00327 if (::setsockopt(rsock_, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
00328 sizeof(on)) < 0) {
00329 fprintf(stderr,
00330 "UDPIPNetwork(%s): open: warning: unable set REUSEADDR: %s\n",
00331 name(), strerror(errno));
00332 }
00333 #ifdef SO_REUSEPORT
00334 on = 1;
00335 if (::setsockopt(rsock_, SOL_SOCKET, SO_REUSEPORT, (char *)&on,
00336 sizeof(on)) < 0) {
00337 fprintf(stderr,
00338 "UDPIPNetwork(%s): open: warning: unable set REUSEPORT: %s\n",
00339 name(), strerror(errno));
00340 }
00341 #endif
00342
00343
00344
00345 if (rbufsize(rsock_, 80*1024) < 0) {
00346 if (rbufsize(rsock_, 32*1024) < 0) {
00347 fprintf(stderr,
00348 "UDPIPNetwork(%s): open: unable to set r bufsize to %d: %s\n",
00349 name(), 32*1024, strerror(errno));
00350 }
00351 }
00352 }
00353 if (mode == O_WRONLY || mode == O_RDWR) {
00354 ssock_ = socket(AF_INET, SOCK_DGRAM, 0);
00355 if (ssock_ < 0) {
00356 fprintf(stderr,
00357 "UDPIPNetwork(%s): open: couldn't open snd sock\n",
00358 name());
00359 }
00360 nonblock(ssock_);
00361 int firsttry = 80 * 1024;
00362 int secondtry = 48 * 1024;
00363
00364 if (sbufsize(ssock_, firsttry) < 0) {
00365 if (sbufsize(ssock_, secondtry) < 0) {
00366 fprintf(stderr,
00367 "UDPIPNetwork(%s): open: cannot set send sockbuf size to %d bytes, using default\n",
00368 name(), secondtry);
00369 }
00370 }
00371
00372 }
00373 mode_ = mode;
00374 NIDEBUG5("UDPIPNetwork(%s): opened network w/mode %d, ssock:%d, rsock:%d\n",
00375 name(), mode_, rsock_, ssock_);
00376 return (0);
00377 }
00378
00379
00380
00381
00382
00383 void
00384 UDPIPNetwork::add_membership(Socket sock, in_addr& addr, u_int16_t port)
00385 {
00386 int failure = 0;
00387 sockaddr_in sin;
00388 if (bindsock(sock, addr, port, sin) < 0)
00389 failure = 1;
00390 if (failure) {
00391 in_addr addr2 = addr;
00392 addr2.s_addr = INADDR_ANY;
00393 if (bindsock(sock, addr2, port, sin) < 0)
00394 failure = 1;
00395 else
00396 failure = 0;
00397 }
00398
00399 if (IPNetwork::add_membership(sock, addr) < 0)
00400 failure = 1;
00401
00402 if (failure) {
00403 fprintf(stderr,
00404 "UDPIPNetwork(%s): add_membership: failed bind on mcast addr %s and INADDR_ANY\n",
00405 name(), inet_ntoa(addr));
00406 }
00407 }
00408
00409
00410
00411
00412 int
00413 UDPIPNetwork::bind(in_addr& addr, u_int16_t port)
00414 {
00415 NIDEBUG4("UDPIPNetwork(%s): attempt to bind to addr %s, port %d [net order]\n",
00416 name(), inet_ntoa(addr), ntohs(port));
00417 if (rsock_ < 0) {
00418 fprintf(stderr,
00419 "UDPIPNetwork(%s): bind/listen called before net is open\n",
00420 name());
00421 return (-1);
00422 }
00423 if (mode_ == O_WRONLY) {
00424 fprintf(stderr,
00425 "UDPIPNetwork(%s): attempted bind/listen but net is write-only\n",
00426 name());
00427 return (-1);
00428 }
00429 #ifdef IP_ADD_MEMBERSHIP
00430 if (IN_CLASSD(ntohl(addr.s_addr))) {
00431
00432 add_membership(rsock_, addr, port);
00433 } else
00434 #endif
00435 {
00436
00437 sockaddr_in sin;
00438 if (bindsock(rsock_, addr, port, sin) < 0) {
00439 port = ntohs(port);
00440 fprintf(stderr,
00441 "UDPIPNetwork(%s): bind: unable to bind %s [port:%hu]: %s\n",
00442 name(), inet_ntoa(addr),
00443 port, strerror(errno));
00444 return (-1);
00445 }
00446
00447
00448
00449
00450
00451 #ifndef WIN32
00452
00453
00454
00455 (void)connectsock(rsock_, addr, 0, sin);
00456 #endif
00457 }
00458 localaddr_ = addr;
00459 lport_ = port;
00460 return (0);
00461 }
00462
00463
00464
00465
00466 int
00467 UDPIPNetwork::connect(in_addr& addr, u_int16_t port)
00468 {
00469 sockaddr_in sin;
00470 if (ssock_ < 0) {
00471 fprintf(stderr,
00472 "UDPIPNetwork(%s): connect called before net is open\n",
00473 name());
00474 return (-1);
00475 }
00476 if (mode_ == O_RDONLY) {
00477 fprintf(stderr,
00478 "UDPIPNetwork(%s): attempted connect but net is read-only\n",
00479 name());
00480 return (-1);
00481 }
00482
00483 int rval = connectsock(ssock_, addr, port, sin);
00484 if (rval < 0)
00485 return (rval);
00486 destaddr_ = addr;
00487 port_ = port;
00488 last_reset_ = 0;
00489 return(rval);
00490 }
00491
00492 int
00493 UDPIPNetwork::command(int argc, const char*const* argv)
00494 {
00495 Tcl& tcl = Tcl::instance();
00496 if (argc == 2) {
00497
00498 if (strcmp(argv[1], "port") == 0) {
00499 tcl.resultf("%d", ntohs(port_));
00500 return (TCL_OK);
00501 }
00502
00503 if (strcmp(argv[1], "lport") == 0) {
00504 tcl.resultf("%d", ntohs(lport_));
00505 return (TCL_OK);
00506 }
00507 } else if (argc == 4) {
00508
00509
00510 if (strcmp(argv[1], "listen") == 0 ||
00511 strcmp(argv[1], "bind") == 0) {
00512 in_addr addr;
00513 if (strcmp(argv[2], "any") == 0)
00514 addr.s_addr = INADDR_ANY;
00515 else
00516 addr.s_addr = LookupHostAddr(argv[2]);
00517 u_int16_t port = htons(atoi(argv[3]));
00518 if (bind(addr, port) < 0) {
00519 tcl.resultf("%s %hu",
00520 inet_ntoa(addr), port);
00521 } else {
00522 tcl.result("0");
00523 }
00524 return (TCL_OK);
00525 }
00526
00527 if (strcmp(argv[1], "connect") == 0) {
00528 in_addr addr;
00529 addr.s_addr = LookupHostAddr(argv[2]);
00530 u_int16_t port = htons(atoi(argv[3]));
00531 if (connect(addr, port) < 0) {
00532 tcl.resultf("%s %hu",
00533 inet_ntoa(addr), port);
00534 } else {
00535 tcl.result("0");
00536 }
00537 return (TCL_OK);
00538 }
00539 }
00540 return (IPNetwork::command(argc, argv));
00541 }
00542
00543
00544
00545
00546 int
00547 IPNetwork::recv(u_char* buf, int len, sockaddr& sa, double& ts)
00548 {
00549 if (mode_ == O_WRONLY) {
00550 fprintf(stderr,
00551 "IPNetwork(%s) recv while in writeonly mode!\n",
00552 name());
00553 abort();
00554 }
00555 int fromlen = sizeof(sa);
00556 int cc = ::recvfrom(rsock_, (char*)buf, len, 0, &sa, (socklen_t*)&fromlen);
00557 if (cc < 0) {
00558 if (errno != EWOULDBLOCK)
00559 perror("recvfrom");
00560 return (-1);
00561 }
00562 ts = Scheduler::instance().clock();
00563 return (cc);
00564 }
00565
00566
00567
00568
00569
00570
00571
00572 int
00573 IPNetwork::send(u_char* buf, int len)
00574 {
00575 struct ip *ip = (struct ip*) buf;
00576 #ifdef __linux__
00577
00578
00579
00580 ip->ip_len = (ip->ip_len);
00581 ip->ip_off = (ip->ip_off);
00582 sockaddr_in sin;
00583 memset((char *)&sin, 0, sizeof(sin));
00584 sin.sin_family = AF_INET;
00585 sin.sin_addr = ip->ip_dst;
00586 return (::sendto(ssock_, (char*)buf, len, 0,(sockaddr *) &sin,sizeof(sin)));
00587 #else
00588 ip->ip_len = ntohs(ip->ip_len);
00589 ip->ip_off = ntohs(ip->ip_off);
00590 return (::send(ssock_, (char*)buf, len, 0));
00591 #endif
00592 }
00593
00594 int IPNetwork::command(int argc, const char*const* argv)
00595 {
00596 Tcl& tcl = Tcl::instance();
00597 if (argc == 2) {
00598 if (strcmp(argv[1], "close") == 0) {
00599 close();
00600 return (TCL_OK);
00601 }
00602
00603
00604
00605
00606 if (strcmp(argv[1], "destaddr") == 0) {
00607 tcl.result(inet_ntoa(destaddr_));
00608 return (TCL_OK);
00609 }
00610 if (strcmp(argv[1], "localaddr") == 0) {
00611 tcl.result(inet_ntoa(localaddr_));
00612 return (TCL_OK);
00613 }
00614 if (strcmp(argv[1], "mttl") == 0) {
00615 tcl.resultf("%d", mttl_);
00616 return (TCL_OK);
00617 }
00618
00619 if (strcmp(argv[1], "ismulticast") == 0) {
00620 tcl.result(IN_CLASSD(ntohl(destaddr_.s_addr)) ?
00621 "1" : "0");
00622 return (TCL_OK);
00623 }
00624 if (strcmp(argv[1], "addr") == 0) {
00625 tcl.result(inet_ntoa(destaddr_));
00626 return (TCL_OK);
00627 }
00628 if (strcmp(argv[1], "ttl") == 0) {
00629 tcl.resultf("%d", mttl_);
00630 return (TCL_OK);
00631 }
00632 if (strcmp(argv[1], "interface") == 0) {
00633 tcl.result(inet_ntoa(localaddr_));
00634 return (TCL_OK);
00635 }
00636 } else if (argc == 3) {
00637
00638 if (strcmp(argv[1], "open") == 0) {
00639 int mode = parsemode(argv[2]);
00640 if (open(mode) < 0)
00641 return (TCL_ERROR);
00642 return (TCL_OK);
00643 }
00644 if (strcmp(argv[1], "add-membership") == 0) {
00645 in_addr addr;
00646 addr.s_addr = LookupHostAddr(argv[2]);
00647 if (add_membership(rchannel(), addr) < 0)
00648 tcl.result("0");
00649 else
00650 tcl.result("1");
00651 return (TCL_OK);
00652 }
00653 if (strcmp(argv[1], "drop-membership") == 0) {
00654 in_addr addr;
00655 addr.s_addr = LookupHostAddr(argv[2]);
00656 if (drop_membership(rchannel(), addr) < 0)
00657 tcl.result("0");
00658 else
00659 tcl.result("1");
00660 return (TCL_OK);
00661 }
00662 if (strcmp(argv[1], "loopback") == 0) {
00663 int val = atoi(argv[2]);
00664 if (strcmp(argv[2], "true") == 0)
00665 val = 1;
00666 else if (strcmp(argv[2], "false") == 0)
00667 val = 0;
00668 if (setmloop(schannel(), val) < 0)
00669 tcl.result("0");
00670 else
00671 tcl.result("1");
00672 return (TCL_OK);
00673 }
00674 }
00675 return (Network::command(argc, argv));
00676 }
00677 int
00678 IPNetwork::setmttl(Socket s, int ttl)
00679 {
00680
00681
00682 #ifdef WIN32
00683 u_int t = ttl;
00684 #else
00685 u_char t = ttl;
00686 #endif
00687
00688 t = (ttl > 255) ? 255 : (ttl < 0) ? 0 : ttl;
00689 if (::setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
00690 (char*)&t, sizeof(t)) < 0) {
00691 fprintf(stderr,
00692 "IPNetwork(%s): couldn't set multicast ttl to %d\n",
00693 name(), t);
00694 return (-1);
00695 }
00696 return (0);
00697 }
00698
00699
00700
00701
00702
00703
00704 int
00705 IPNetwork::open(int mode)
00706 {
00707
00708 Socket fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
00709 if (fd < 0) {
00710 perror("socket(RAW)");
00711 if (::getuid() != 0 && ::geteuid() != 0) {
00712 fprintf(stderr,
00713 "IPNetwork(%s): open: use of the Network/IP object requires super-user privs\n",
00714 name());
00715 }
00716
00717 return (-1);
00718 }
00719
00720
00721
00722
00723
00724 int one = 1;
00725 if (::setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0) {
00726 fprintf(stderr,
00727 "IPNetwork(%s): open: unable to turn on IP_HDRINCL: %s\n",
00728 name(), strerror(errno));
00729 return (-1);
00730 }
00731 #ifndef __linux__
00732
00733
00734 sockaddr_in sin;
00735 in_addr ia = { INADDR_ANY };
00736 if (connectsock(fd, ia, 0, sin) < 0) {
00737 fprintf(stderr,
00738 "IPNetwork(%s): open: unable to connect : %s\n",
00739 name(), strerror(errno));
00740 }
00741 #endif
00742 rsock_ = ssock_ = fd;
00743 mode_ = mode;
00744 NIDEBUG5("IPNetwork(%s): opened with mode %d, rsock_:%d, ssock_:%d\n",
00745 name(), mode_, rsock_, ssock_);
00746 return 0;
00747 }
00748
00749
00750
00751
00752
00753 int
00754 IPNetwork::close()
00755 {
00756 if (ssock_ >= 0) {
00757 (void)::close(ssock_);
00758 ssock_ = -1;
00759 }
00760 if (rsock_ >= 0) {
00761 (void)::close(rsock_);
00762 rsock_ = -1;
00763 }
00764 return (0);
00765 }
00766
00767
00768
00769
00770
00771 int
00772 IPNetwork::add_membership(Socket fd, in_addr& addr)
00773 {
00774
00775 #if defined(IP_ADD_MEMBERSHIP)
00776 if (IN_CLASSD(ntohl(addr.s_addr))) {
00777 #ifdef notdef
00778
00779
00780
00781
00782
00783
00784 sockaddr_in sin;
00785 memset(&sin, 0, sizeof(sin));
00786 sin.sin_family = AF_INET;
00787 sin.sin_addr = addr;
00788 if (::bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
00789 sin.sin_addr.s_addr = INADDR_ANY;
00790 if (::bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
00791 fprintf(stderr,
00792 "IPNetwork(%s): add_membership: unable to bind to addr %s: %s\n",
00793 name(), inet_ntoa(sin.sin_addr),
00794 strerror(errno));
00795 return (-1);
00796 }
00797 }
00798 #endif
00799
00800
00801
00802
00803
00804
00805
00806
00807 struct ip_mreq mr;
00808
00809 mr.imr_multiaddr = addr;
00810 mr.imr_interface.s_addr = INADDR_ANY;
00811 if (::setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
00812 (char *)&mr, sizeof(mr)) < 0) {
00813 fprintf(stderr, "IPNetwork(%s): add_membership: unable to add membership for addr %s: %s\n",
00814 name(), inet_ntoa(addr), strerror(errno));
00815 return (-1);
00816 }
00817 NIDEBUG3("IPNetwork(%s): add_membership for grp %s done\n",
00818 name(), inet_ntoa(addr));
00819 return (0);
00820 }
00821 #else
00822 fprintf(stderr, "IPNetwork(%s): add_membership: host does not support IP multicast\n",
00823 name());
00824 #endif
00825 NIDEBUG3("IPNetwork(%s): add_membership for grp %s failed\n",
00826 name(), inet_ntoa(addr));
00827 return (-1);
00828 }
00829
00830
00831
00832
00833
00834 int
00835 IPNetwork::drop_membership(Socket fd, in_addr& addr)
00836 {
00837
00838 #if defined(IP_DROP_MEMBERSHIP)
00839 if (IN_CLASSD(ntohl(addr.s_addr))) {
00840 struct ip_mreq mr;
00841
00842 mr.imr_multiaddr = addr;
00843 mr.imr_interface.s_addr = INADDR_ANY;
00844 if (::setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
00845 (char *)&mr, sizeof(mr)) < 0) {
00846 fprintf(stderr, "IPNetwork(%s): drop_membership: unable to drop membership for addr %s: %s\n",
00847 name(), inet_ntoa(addr), strerror(errno));
00848 return (-1);
00849 }
00850 NIDEBUG3("IPNetwork(%s): drop_membership for grp %s done\n",
00851 name(), inet_ntoa(addr));
00852 return (0);
00853 }
00854 #else
00855 fprintf(stderr, "IPNetwork(%s): drop_membership: host does not support IP multicast\n",
00856 name());
00857 #endif
00858 NIDEBUG3("IPNetwork(%s): drop_membership for grp %s failed\n",
00859 name(), inet_ntoa(addr));
00860 return (-1);
00861 }
00862
00863 int
00864 IPNetwork::bindsock(Socket s, in_addr& addr, u_int16_t port, sockaddr_in& sin)
00865 {
00866 memset((char *)&sin, 0, sizeof(sin));
00867 sin.sin_family = AF_INET;
00868 sin.sin_port = port;
00869 sin.sin_addr = addr;
00870 return(::bind(s, (struct sockaddr *)&sin, sizeof(sin)));
00871 }
00872
00873 int
00874 IPNetwork::connectsock(Socket s, in_addr& addr, u_int16_t port, sockaddr_in& sin)
00875 {
00876 memset((char *)&sin, 0, sizeof(sin));
00877 sin.sin_family = AF_INET;
00878 sin.sin_port = port;
00879 sin.sin_addr = addr;
00880 return(::connect(s, (struct sockaddr *)&sin, sizeof(sin)));
00881 }
00882 int
00883 IPNetwork::sbufsize(Socket s, int cnt)
00884 {
00885 return(::setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&cnt, sizeof(cnt)));
00886 }
00887
00888 int
00889 IPNetwork::rbufsize(Socket s, int cnt)
00890 {
00891 return(::setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&cnt, sizeof(cnt)));
00892 }
00893
00894 int
00895 IPNetwork::setmloop(Socket s, int loop)
00896 {
00897
00898 #ifdef IP_MULTICAST_LOOP
00899 u_char c = loop;
00900
00901 if (::setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &c, sizeof(c)) < 0) {
00902
00903
00904
00905
00906
00907
00908 if (c != loop) {
00909 noloopback_broken_ = 1;
00910 loop_ = c;
00911 }
00912 return (-1);
00913 }
00914 noloopback_broken_ = 0;
00915 #else
00916 fprintf(stderr, "IPNetwork(%s): msetloop: host does not support IP multicast\n",
00917 name());
00918 #endif
00919 loop_ = c;
00920 return (0);
00921 }
00922
00923 void
00924 IPNetwork::reset(int restart)
00925 {
00926 time_t t = time(0);
00927 int d = int(t - last_reset_);
00928 NIDEBUG2("IPNetwork(%s): reset\n", name());
00929 if (d > 3) {
00930 last_reset_ = t;
00931 if (ssock_ >= 0)
00932 (void)::close(ssock_);
00933 if (rsock_ >= 0)
00934 (void)::close(rsock_);
00935 if (open(mode_) < 0) {
00936 fprintf(stderr,
00937 "IPNetwork(%s): couldn't reset\n",
00938 name());
00939 mode_ = -1;
00940 return;
00941 }
00942 if (restart)
00943 (void) reconfigure();
00944 }
00945 }
00946
00947
00948
00949
00950
00951
00952 void
00953 IPNetwork::reconfigure()
00954 {
00955 }
00956
00957 void
00958 UDPIPNetwork::reconfigure()
00959 {
00960 }