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.19 2001/09/20 19:05:50 alefiyah 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 char* cp = tcl.result();
00603 if (strcmp(argv[1], "destaddr") == 0) {
00604 strcpy(cp, inet_ntoa(destaddr_));
00605 return (TCL_OK);
00606 }
00607 if (strcmp(argv[1], "localaddr") == 0) {
00608 strcpy(cp, inet_ntoa(localaddr_));
00609 return (TCL_OK);
00610 }
00611 if (strcmp(argv[1], "mttl") == 0) {
00612 tcl.resultf("%d", mttl_);
00613 return (TCL_OK);
00614 }
00615
00616 if (strcmp(argv[1], "ismulticast") == 0) {
00617 tcl.result(IN_CLASSD(ntohl(destaddr_.s_addr)) ?
00618 "1" : "0");
00619 return (TCL_OK);
00620 }
00621 if (strcmp(argv[1], "addr") == 0) {
00622 strcpy(cp, inet_ntoa(destaddr_));
00623 return (TCL_OK);
00624 }
00625 if (strcmp(argv[1], "ttl") == 0) {
00626 tcl.resultf("%d", mttl_);
00627 return (TCL_OK);
00628 }
00629 if (strcmp(argv[1], "interface") == 0) {
00630 strcpy(cp, inet_ntoa(localaddr_));
00631 return (TCL_OK);
00632 }
00633 } else if (argc == 3) {
00634
00635 if (strcmp(argv[1], "open") == 0) {
00636 int mode = parsemode(argv[2]);
00637 if (open(mode) < 0)
00638 return (TCL_ERROR);
00639 return (TCL_OK);
00640 }
00641 if (strcmp(argv[1], "add-membership") == 0) {
00642 in_addr addr;
00643 addr.s_addr = LookupHostAddr(argv[2]);
00644 if (add_membership(rchannel(), addr) < 0)
00645 tcl.result("0");
00646 else
00647 tcl.result("1");
00648 return (TCL_OK);
00649 }
00650 if (strcmp(argv[1], "drop-membership") == 0) {
00651 in_addr addr;
00652 addr.s_addr = LookupHostAddr(argv[2]);
00653 if (drop_membership(rchannel(), addr) < 0)
00654 tcl.result("0");
00655 else
00656 tcl.result("1");
00657 return (TCL_OK);
00658 }
00659 if (strcmp(argv[1], "loopback") == 0) {
00660 int val = atoi(argv[2]);
00661 if (strcmp(argv[2], "true") == 0)
00662 val = 1;
00663 else if (strcmp(argv[2], "false") == 0)
00664 val = 0;
00665 if (setmloop(schannel(), val) < 0)
00666 tcl.result("0");
00667 else
00668 tcl.result("1");
00669 return (TCL_OK);
00670 }
00671 }
00672 return (Network::command(argc, argv));
00673 }
00674 int
00675 IPNetwork::setmttl(Socket s, int ttl)
00676 {
00677
00678
00679 #ifdef WIN32
00680 u_int t = ttl;
00681 #else
00682 u_char t = ttl;
00683 #endif
00684
00685 t = (ttl > 255) ? 255 : (ttl < 0) ? 0 : ttl;
00686 if (::setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
00687 (char*)&t, sizeof(t)) < 0) {
00688 fprintf(stderr,
00689 "IPNetwork(%s): couldn't set multicast ttl to %d\n",
00690 name(), t);
00691 return (-1);
00692 }
00693 return (0);
00694 }
00695
00696
00697
00698
00699
00700
00701 int
00702 IPNetwork::open(int mode)
00703 {
00704
00705 Socket fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
00706 if (fd < 0) {
00707 perror("socket(RAW)");
00708 if (::getuid() != 0 && ::geteuid() != 0) {
00709 fprintf(stderr,
00710 "IPNetwork(%s): open: use of the Network/IP object requires super-user privs\n",
00711 name());
00712 }
00713
00714 return (-1);
00715 }
00716
00717
00718
00719
00720
00721 int one = 1;
00722 if (::setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0) {
00723 fprintf(stderr,
00724 "IPNetwork(%s): open: unable to turn on IP_HDRINCL: %s\n",
00725 name(), strerror(errno));
00726 return (-1);
00727 }
00728 #ifndef __linux__
00729
00730
00731 sockaddr_in sin;
00732 in_addr ia = { INADDR_ANY };
00733 if (connectsock(fd, ia, 0, sin) < 0) {
00734 fprintf(stderr,
00735 "IPNetwork(%s): open: unable to connect : %s\n",
00736 name(), strerror(errno));
00737 }
00738 #endif
00739 rsock_ = ssock_ = fd;
00740 mode_ = mode;
00741 NIDEBUG5("IPNetwork(%s): opened with mode %d, rsock_:%d, ssock_:%d\n",
00742 name(), mode_, rsock_, ssock_);
00743 return 0;
00744 }
00745
00746
00747
00748
00749
00750 int
00751 IPNetwork::close()
00752 {
00753 if (ssock_ >= 0) {
00754 (void)::close(ssock_);
00755 ssock_ = -1;
00756 }
00757 if (rsock_ >= 0) {
00758 (void)::close(rsock_);
00759 rsock_ = -1;
00760 }
00761 return (0);
00762 }
00763
00764
00765
00766
00767
00768 int
00769 IPNetwork::add_membership(Socket fd, in_addr& addr)
00770 {
00771
00772 #if defined(IP_ADD_MEMBERSHIP)
00773 if (IN_CLASSD(ntohl(addr.s_addr))) {
00774 #ifdef notdef
00775
00776
00777
00778
00779
00780
00781 sockaddr_in sin;
00782 memset(&sin, 0, sizeof(sin));
00783 sin.sin_family = AF_INET;
00784 sin.sin_addr = addr;
00785 if (::bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
00786 sin.sin_addr.s_addr = INADDR_ANY;
00787 if (::bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
00788 fprintf(stderr,
00789 "IPNetwork(%s): add_membership: unable to bind to addr %s: %s\n",
00790 name(), inet_ntoa(sin.sin_addr),
00791 strerror(errno));
00792 return (-1);
00793 }
00794 }
00795 #endif
00796
00797
00798
00799
00800
00801
00802
00803
00804 struct ip_mreq mr;
00805
00806 mr.imr_multiaddr = addr;
00807 mr.imr_interface.s_addr = INADDR_ANY;
00808 if (::setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
00809 (char *)&mr, sizeof(mr)) < 0) {
00810 fprintf(stderr, "IPNetwork(%s): add_membership: unable to add membership for addr %s: %s\n",
00811 name(), inet_ntoa(addr), strerror(errno));
00812 return (-1);
00813 }
00814 NIDEBUG3("IPNetwork(%s): add_membership for grp %s done\n",
00815 name(), inet_ntoa(addr));
00816 return (0);
00817 }
00818 #else
00819 fprintf(stderr, "IPNetwork(%s): add_membership: host does not support IP multicast\n",
00820 name());
00821 #endif
00822 NIDEBUG3("IPNetwork(%s): add_membership for grp %s failed\n",
00823 name(), inet_ntoa(addr));
00824 return (-1);
00825 }
00826
00827
00828
00829
00830
00831 int
00832 IPNetwork::drop_membership(Socket fd, in_addr& addr)
00833 {
00834
00835 #if defined(IP_DROP_MEMBERSHIP)
00836 if (IN_CLASSD(ntohl(addr.s_addr))) {
00837 struct ip_mreq mr;
00838
00839 mr.imr_multiaddr = addr;
00840 mr.imr_interface.s_addr = INADDR_ANY;
00841 if (::setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
00842 (char *)&mr, sizeof(mr)) < 0) {
00843 fprintf(stderr, "IPNetwork(%s): drop_membership: unable to drop membership for addr %s: %s\n",
00844 name(), inet_ntoa(addr), strerror(errno));
00845 return (-1);
00846 }
00847 NIDEBUG3("IPNetwork(%s): drop_membership for grp %s done\n",
00848 name(), inet_ntoa(addr));
00849 return (0);
00850 }
00851 #else
00852 fprintf(stderr, "IPNetwork(%s): drop_membership: host does not support IP multicast\n",
00853 name());
00854 #endif
00855 NIDEBUG3("IPNetwork(%s): drop_membership for grp %s failed\n",
00856 name(), inet_ntoa(addr));
00857 return (-1);
00858 }
00859
00860 int
00861 IPNetwork::bindsock(Socket s, in_addr& addr, u_int16_t port, sockaddr_in& sin)
00862 {
00863 memset((char *)&sin, 0, sizeof(sin));
00864 sin.sin_family = AF_INET;
00865 sin.sin_port = port;
00866 sin.sin_addr = addr;
00867 return(::bind(s, (struct sockaddr *)&sin, sizeof(sin)));
00868 }
00869
00870 int
00871 IPNetwork::connectsock(Socket s, in_addr& addr, u_int16_t port, sockaddr_in& sin)
00872 {
00873 memset((char *)&sin, 0, sizeof(sin));
00874 sin.sin_family = AF_INET;
00875 sin.sin_port = port;
00876 sin.sin_addr = addr;
00877 return(::connect(s, (struct sockaddr *)&sin, sizeof(sin)));
00878 }
00879 int
00880 IPNetwork::sbufsize(Socket s, int cnt)
00881 {
00882 return(::setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&cnt, sizeof(cnt)));
00883 }
00884
00885 int
00886 IPNetwork::rbufsize(Socket s, int cnt)
00887 {
00888 return(::setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&cnt, sizeof(cnt)));
00889 }
00890
00891 int
00892 IPNetwork::setmloop(Socket s, int loop)
00893 {
00894
00895 #ifdef IP_MULTICAST_LOOP
00896 u_char c = loop;
00897
00898 if (::setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &c, sizeof(c)) < 0) {
00899
00900
00901
00902
00903
00904
00905 if (c != loop) {
00906 noloopback_broken_ = 1;
00907 loop_ = c;
00908 }
00909 return (-1);
00910 }
00911 noloopback_broken_ = 0;
00912 #else
00913 fprintf(stderr, "IPNetwork(%s): msetloop: host does not support IP multicast\n",
00914 name());
00915 #endif
00916 loop_ = c;
00917 return (0);
00918 }
00919
00920 void
00921 IPNetwork::reset(int restart)
00922 {
00923 time_t t = time(0);
00924 int d = int(t - last_reset_);
00925 NIDEBUG2("IPNetwork(%s): reset\n", name());
00926 if (d > 3) {
00927 last_reset_ = t;
00928 if (ssock_ >= 0)
00929 (void)::close(ssock_);
00930 if (rsock_ >= 0)
00931 (void)::close(rsock_);
00932 if (open(mode_) < 0) {
00933 fprintf(stderr,
00934 "IPNetwork(%s): couldn't reset\n",
00935 name());
00936 mode_ = -1;
00937 return;
00938 }
00939 if (restart)
00940 (void) reconfigure();
00941 }
00942 }
00943
00944
00945
00946
00947
00948
00949 void
00950 IPNetwork::reconfigure()
00951 {
00952 }
00953
00954 void
00955 UDPIPNetwork::reconfigure()
00956 {
00957 }