📄 net-ip.cc
字号:
return (-1); } if (mode_ == O_RDONLY) { fprintf(stderr, "UDPIPNetwork(%s): attempted connect but net is read-only\n", name()); return (-1); } int rval = connectsock(ssock_, addr, port, sin); if (rval < 0) return (rval); destaddr_ = addr; port_ = port; last_reset_ = 0; return(rval);}intUDPIPNetwork::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 2) { // $udpip port if (strcmp(argv[1], "port") == 0) { tcl.resultf("%d", ntohs(port_)); return (TCL_OK); } // $udpip lport if (strcmp(argv[1], "lport") == 0) { tcl.resultf("%d", ntohs(lport_)); return (TCL_OK); } } else if (argc == 4) { // $udpip listen addr port // $udpip bind addr port if (strcmp(argv[1], "listen") == 0 || strcmp(argv[1], "bind") == 0) { in_addr addr; if (strcmp(argv[2], "any") == 0) addr.s_addr = INADDR_ANY; else addr.s_addr = LookupHostAddr(argv[2]); u_int16_t port = htons(atoi(argv[3])); if (bind(addr, port) < 0) { tcl.resultf("%s %hu", inet_ntoa(addr), port); } else { tcl.result("0"); } return (TCL_OK); } // $udpip connect addr port if (strcmp(argv[1], "connect") == 0) { in_addr addr; addr.s_addr = LookupHostAddr(argv[2]); u_int16_t port = htons(atoi(argv[3])); if (connect(addr, port) < 0) { tcl.resultf("%s %hu", inet_ntoa(addr), port); } else { tcl.result("0"); } return (TCL_OK); } } return (IPNetwork::command(argc, argv));}//// raw IP network recv()//intIPNetwork::recv(u_char* buf, int len, sockaddr& sa, double& ts){ if (mode_ == O_WRONLY) { fprintf(stderr, "IPNetwork(%s) recv while in writeonly mode!\n", name()); abort(); } int fromlen = sizeof(sa); int cc = ::recvfrom(rsock_, (char*)buf, len, 0, &sa, &fromlen); if (cc < 0) { if (errno != EWOULDBLOCK) perror("recvfrom"); return (-1); } ts = Scheduler::instance().clock(); return (cc);}//// we are given a "raw" IP datagram.// the raw interface appears to want the len and off fields// in *host* order, so make it this way here// note also, that it will compute the cksum "for" us... :(//intIPNetwork::send(u_char* buf, int len){ struct ip *ip = (struct ip*) buf; ip->ip_len = ntohs(ip->ip_len); ip->ip_off = ntohs(ip->ip_off); return (::send(ssock_, (char*)buf, len, 0));}int IPNetwork::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 2) { if (strcmp(argv[1], "close") == 0) { close(); return (TCL_OK); } char* cp = tcl.result(); if (strcmp(argv[1], "destaddr") == 0) { strcpy(cp, inet_ntoa(destaddr_)); return (TCL_OK); } if (strcmp(argv[1], "localaddr") == 0) { strcpy(cp, inet_ntoa(localaddr_)); return (TCL_OK); } if (strcmp(argv[1], "mttl") == 0) { tcl.resultf("%d", mttl_); return (TCL_OK); } /* for backward compatability */ if (strcmp(argv[1], "ismulticast") == 0) { tcl.result(IN_CLASSD(ntohl(destaddr_.s_addr)) ? "1" : "0"); return (TCL_OK); } if (strcmp(argv[1], "addr") == 0) { strcpy(cp, inet_ntoa(destaddr_)); return (TCL_OK); } if (strcmp(argv[1], "ttl") == 0) { tcl.resultf("%d", mttl_); return (TCL_OK); } if (strcmp(argv[1], "interface") == 0) { strcpy(cp, inet_ntoa(localaddr_)); return (TCL_OK); } } else if (argc == 3) { if (strcmp(argv[1], "open") == 0) { int mode = parsemode(argv[2]); if (open(mode) < 0) return (TCL_ERROR); return (TCL_OK); } if (strcmp(argv[1], "add-membership") == 0) { in_addr addr; addr.s_addr = LookupHostAddr(argv[2]); if (add_membership(rchannel(), addr) < 0) tcl.result("0"); else tcl.result("1"); return (TCL_OK); } if (strcmp(argv[1], "drop-membership") == 0) { in_addr addr; addr.s_addr = LookupHostAddr(argv[2]); if (drop_membership(rchannel(), addr) < 0) tcl.result("0"); else tcl.result("1"); return (TCL_OK); } if (strcmp(argv[1], "loopback") == 0) { int val = atoi(argv[2]); if (strcmp(argv[2], "true") == 0) val = 1; else if (strcmp(argv[2], "false") == 0) val = 0; if (setmloop(schannel(), val) < 0) tcl.result("0"); else tcl.result("1"); return (TCL_OK); } } return (Network::command(argc, argv));}intIPNetwork::setmttl(Socket s, int ttl){ /* set the multicast TTL */ #ifdef WIN32 u_int t = ttl; #else u_char t = ttl;#endif t = (ttl > 255) ? 255 : (ttl < 0) ? 0 : ttl; if (::setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&t, sizeof(t)) < 0) { fprintf(stderr, "IPNetwork(%s): couldn't set multicast ttl to %d\n", name(), t); return (-1); } return (0);}/* * open a RAW IP socket (will require privilege). * turn on HDRINCL, specifying that we will be writing the raw IP header */intIPNetwork::open(int mode){ // obtain a raw socket we can use to send ip datagrams Socket fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (fd < 0) { perror("socket(RAW)"); if (::getuid() != 0 && ::geteuid() != 0) { fprintf(stderr, "IPNetwork(%s): open: use of the Network/IP object requires super-user privs\n", name()); } return (-1); } // turn on HDRINCL option (we will be writing IP header) // in FreeBSD 2.2.5 (and possibly others), the IP id field // is set by the kernel routine rip_output() // only if it is non-zero, so we should be ok. int one = 1; if (::setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0) { fprintf(stderr, "IPNetwork(%s): open: unable to turn on IP_HDRINCL: %s\n", name(), strerror(errno)); return (-1); } // sort of curious, but do a connect() even though we have // HDRINCL on. Otherwise, we get ENOTCONN when doing a send() sockaddr_in sin; in_addr ia = { INADDR_ANY }; if (connectsock(fd, ia, 0, sin) < 0) { fprintf(stderr, "IPNetwork(%s): open: unable to connect : %s\n", name(), strerror(errno)); } rsock_ = ssock_ = fd; mode_ = mode; NIDEBUG5("IPNetwork(%s): opened with mode %d, rsock_:%d, ssock_:%d\n", name(), mode_, rsock_, ssock_); return 0;}/* * close both sending and receiving sockets */intIPNetwork::close(){ if (ssock_ >= 0) { (void)::close(ssock_); ssock_ = -1; } if (rsock_ >= 0) { (void)::close(rsock_); rsock_ = -1; } return (0);}/* * add multicast group membership on the socket */intIPNetwork::add_membership(Socket fd, in_addr& addr){#if defined(IP_ADD_MEMBERSHIP) if (IN_CLASSD(ntohl(addr.s_addr))) {#ifdef notdef /* * Try to bind the multicast address as the socket * dest address. On many systems this won't work * so fall back to a destination of INADDR_ANY if * the first bind fails. */ sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = addr; if (::bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { sin.sin_addr.s_addr = INADDR_ANY; if (::bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { fprintf(stderr, "IPNetwork(%s): add_membership: unable to bind to addr %s: %s\n", name(), inet_ntoa(sin.sin_addr), strerror(errno)); return (-1); } }#endif /* * XXX This is bogus multicast setup that really * shouldn't have to be done (group membership should be * implicit in the IP class D address, route should contain * ttl & no loopback flag, etc.). Steve Deering has promised * to fix this for the 4.4bsd release. We're all waiting * with bated breath. */ struct ip_mreq mr; mr.imr_multiaddr = addr; mr.imr_interface.s_addr = INADDR_ANY; if (::setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mr, sizeof(mr)) < 0) { fprintf(stderr, "IPNetwork(%s): add_membership: unable to add membership for addr %s: %s\n", name(), inet_ntoa(addr), strerror(errno)); return (-1); } NIDEBUG3("IPNetwork(%s): add_membership for grp %s done\n", name(), inet_ntoa(addr)); return (0); }#else fprintf(stderr, "IPNetwork(%s): add_membership: host does not support IP multicast\n", name());#endif NIDEBUG3("IPNetwork(%s): add_membership for grp %s failed\n", name(), inet_ntoa(addr)); return (-1);}/* * drop membership from the specified group on the specified socket */intIPNetwork::drop_membership(Socket fd, in_addr& addr){#if defined(IP_DROP_MEMBERSHIP) if (IN_CLASSD(ntohl(addr.s_addr))) { struct ip_mreq mr; mr.imr_multiaddr = addr; mr.imr_interface.s_addr = INADDR_ANY; if (::setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&mr, sizeof(mr)) < 0) { fprintf(stderr, "IPNetwork(%s): drop_membership: unable to drop membership for addr %s: %s\n", name(), inet_ntoa(addr), strerror(errno)); return (-1); } NIDEBUG3("IPNetwork(%s): drop_membership for grp %s done\n", name(), inet_ntoa(addr)); return (0); }#else fprintf(stderr, "IPNetwork(%s): drop_membership: host does not support IP multicast\n", name());#endif NIDEBUG3("IPNetwork(%s): drop_membership for grp %s failed\n", name(), inet_ntoa(addr)); return (-1);}intIPNetwork::bindsock(Socket s, in_addr& addr, u_int16_t port, sockaddr_in& sin){ memset((char *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = port; sin.sin_addr = addr; return(::bind(s, (struct sockaddr *)&sin, sizeof(sin)));}intIPNetwork::connectsock(Socket s, in_addr& addr, u_int16_t port, sockaddr_in& sin){ memset((char *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = port; sin.sin_addr = addr; return(::connect(s, (struct sockaddr *)&sin, sizeof(sin)));}int IPNetwork::sbufsize(Socket s, int cnt){ return(::setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&cnt, sizeof(cnt)));} intIPNetwork::rbufsize(Socket s, int cnt){ return(::setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&cnt, sizeof(cnt)));} intIPNetwork::setmloop(Socket s, int loop){#ifdef IP_MULTICAST_LOOP u_char c = loop; if (::setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &c, sizeof(c)) < 0) { /* * If we cannot turn off loopback (Like on the * Microsoft TCP/IP stack), then declare this * option broken so that our packets can be * filtered on the recv path. */ if (c != loop) { noloopback_broken_ = 1; loop_ = c; } return (-1); } noloopback_broken_ = 0;#else fprintf(stderr, "IPNetwork(%s): msetloop: host does not support IP multicast\n", name());#endif loop_ = c; return (0);}voidIPNetwork::reset(int restart){ time_t t = time(0); int d = int(t - last_reset_); NIDEBUG2("IPNetwork(%s): reset\n", name()); if (d > 3) { // Steve: why? last_reset_ = t; if (ssock_ >= 0) (void)::close(ssock_); if (rsock_ >= 0) (void)::close(rsock_); if (open(mode_) < 0) { fprintf(stderr, "IPNetwork(%s): couldn't reset\n", name()); mode_ = -1; return; } if (restart) (void) reconfigure(); }}/* * after a reset, we may want to re-establish our state * [set up addressing, etc]. Do this here */voidIPNetwork::reconfigure(){}voidUDPIPNetwork::reconfigure(){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -