22 #include <linux/if_tun.h> 24 #include <sys/socket.h> 26 #include <boost/bimap.hpp> 27 #include <boost/circular_buffer.hpp> 29 #include "dccl/arithmetic/field_codec_arithmetic.h" 31 #include "goby/acomms/acomms_constants.h" 32 #include "goby/acomms/amac.h" 33 #include "goby/acomms/connect.h" 34 #include "goby/acomms/ip_codecs.h" 35 #include "goby/acomms/protobuf/modem_message.pb.h" 36 #include "goby/pb/application.h" 37 #include "goby/util/binary.h" 39 #include "ip_gateway_config.pb.h" 43 IPV4_ADDRESS_BITS = 32,
44 MIN_IPV4_HEADER_LENGTH = 5,
52 int tun_alloc(
char* dev);
53 int tun_config(
const char* dev,
const char* host,
unsigned cidr_prefix,
unsigned mtu);
72 void receive_packets();
76 const std::string& payload);
83 const std::string& payload);
85 void icmp_report_queue();
87 std::pair<int, int> to_src_dest_pair(
int srcdest);
88 int from_src_dest_pair(std::pair<int, int> src_dest);
90 int ipv4_to_goby_address(
const std::string& ipv4_address);
91 std::string goby_address_to_ipv4(
int modem_id);
97 int ac_freq(
int srcdest);
101 dccl::Codec dccl_goby_nh_, dccl_ip_, dccl_udp_, dccl_icmp_;
103 int total_addresses_;
111 boost::bimap<int, int> port_map_;
112 int dynamic_port_index_;
113 std::vector<int> dynamic_udp_fd_;
118 std::map<int, boost::circular_buffer<std::string> > outgoing_;
124 : Application(cfg), cfg_(*cfg), dccl_goby_nh_(
"ip_gateway_id_codec_0"),
125 dccl_ip_(
"ip_gateway_id_codec_1"), dccl_udp_(
"ip_gateway_id_codec_2"),
126 dccl_icmp_(
"ip_gateway_id_codec_3"), tun_fd_(-1),
127 total_addresses_((1 << (IPV4_ADDRESS_BITS - cfg_.cidr_netmask_prefix())) -
129 local_address_(0), local_modem_id_(0), netmask_(0),
130 dynamic_port_index_(cfg_.static_udp_port_size())
132 for (
int d = 0; d < total_addresses_; ++d)
134 for (
int s = 0; s < total_addresses_; ++s)
136 int S = from_src_dest_pair(std::make_pair(s, d));
137 std::cout << std::setw(8) << S;
138 if (s != 0 && s != d)
140 std::pair<int, int> sd = to_src_dest_pair(S);
141 std::cout <<
"(" << sd.first <<
"," << sd.second <<
")";
142 assert(sd.first == s && sd.second == d);
145 std::cout <<
"(" << s <<
"," << d <<
")";
148 std::cout << std::endl;
154 Application::subscribe(&IPGateway::handle_data_request,
this,
155 "DataRequest" + goby::util::as<std::string>(local_modem_id_));
156 Application::subscribe(&IPGateway::handle_modem_receive,
this,
157 "Rx" + goby::util::as<std::string>(local_modem_id_));
160 &IPGateway::handle_initiate_transmission);
161 cfg_.mutable_mac_cfg()->set_modem_id(local_modem_id_);
164 void goby::acomms::IPGateway::init_dccl()
166 if (cfg_.model_type() == protobuf::IPGatewayConfig::AUTONOMY_COLLABORATION)
168 if (cfg_.gamma_autonomy() > 1 || cfg_.gamma_autonomy() < 0)
169 glog.is(DIE) &&
glog <<
"gamma_autonomy must be [0, 1]" << std::endl;
171 if (cfg_.gamma_collaboration() > cfg_.gamma_autonomy() || cfg_.gamma_collaboration() < 0)
172 glog.is(DIE) &&
glog <<
"gamma_collaboration must be [0, gamma_autonomy]" << std::endl;
175 dccl::dlog.connect(dccl::logger::INFO, &std::cout);
177 dccl_arithmetic_load(&dccl_goby_nh_);
179 dccl::arith::protobuf::ArithmeticModel addr_model;
180 addr_model.set_name(
"goby.acomms.NetworkHeader.AddrModel");
182 for (
int i = 0, n = (total_addresses_ - 1) * (total_addresses_ - 1); i <= n; ++i)
187 switch (cfg_.model_type())
189 case protobuf::IPGatewayConfig::UNIFORM:
192 case protobuf::IPGatewayConfig::AUTONOMY_COLLABORATION: freq = ac_freq(i);
break;
195 addr_model.add_value_bound(i);
196 addr_model.add_frequency(freq);
200 addr_model.add_value_bound(n);
204 addr_model.set_eof_frequency(0);
205 addr_model.set_out_of_range_frequency(0);
206 glog.is(DEBUG1) &&
glog << addr_model.DebugString() << std::endl;
208 dccl::arith::ModelManager::set_model(addr_model);
210 if (cfg_.total_ports() < cfg_.static_udp_port_size())
212 glog <<
"total_ports must be at least as many as the static_udp_ports defined" 215 for (
int i = 0, n = cfg_.total_ports(); i < n; ++i)
217 if (i < cfg_.static_udp_port_size())
218 port_map_.insert(boost::bimap<int, int>::value_type(i, cfg_.static_udp_port(i)));
220 port_map_.insert(boost::bimap<int, int>::value_type(i, -i));
223 dccl::arith::protobuf::ArithmeticModel port_model;
224 port_model.
set_name(
"goby.acomms.NetworkHeader.PortModel");
225 for (
int i = 0, n = cfg_.total_ports(); i <= n; ++i)
230 port_model.add_value_bound(i);
231 port_model.add_frequency(freq);
235 port_model.add_value_bound(n);
238 port_model.set_eof_frequency(0);
239 port_model.set_out_of_range_frequency(0);
240 dccl::arith::ModelManager::set_model(port_model);
247 dccl_goby_nh_.info_all(&std::cout);
250 void goby::acomms::IPGateway::init_tun()
252 char tun_name[IFNAMSIZ];
254 std::string desired_tun_name =
"tun";
255 if (cfg_.has_tun_number())
256 desired_tun_name += goby::util::as<std::string>(cfg_.tun_number());
258 desired_tun_name +=
"%d";
260 strcpy(tun_name, desired_tun_name.c_str());
261 tun_fd_ = tun_alloc(tun_name);
263 glog.is(DIE) &&
glog <<
"Could not allocate tun interface. Check permissions?" << std::endl;
266 MIN_IPV4_HEADER_LENGTH * 4;
268 int ret = tun_config(tun_name, cfg_.local_ipv4_address().c_str(), cfg_.cidr_netmask_prefix(),
271 glog.is(DIE) &&
glog <<
"Could not configure tun interface. Check IP address: " 272 << cfg_.local_ipv4_address()
273 <<
" and netmask prefix: " << cfg_.cidr_netmask_prefix() << std::endl;
276 inet_aton(cfg_.local_ipv4_address().c_str(), &local_addr);
277 local_address_ = ntohl(local_addr.s_addr);
278 netmask_ = 0xFFFFFFFF - ((1 << (IPV4_ADDRESS_BITS - cfg_.cidr_netmask_prefix())) - 1);
279 local_modem_id_ = ipv4_to_goby_address(cfg_.local_ipv4_address());
282 goby::acomms::IPGateway::~IPGateway() { dccl_arithmetic_unload(&dccl_goby_nh_); }
284 void goby::acomms::IPGateway::loop()
292 const std::string& payload)
294 glog.is(VERBOSE) &&
glog <<
"Received UDP Packet. IPv4 Header: " << ip_hdr.DebugString()
295 <<
"UDP Header: " << udp_hdr <<
"Payload (" << payload.size()
296 <<
" bytes): " << goby::util::hex_encode(payload) << std::endl;
298 int src = ipv4_to_goby_address(ip_hdr.source_ip_address());
299 int dest = ipv4_to_goby_address(ip_hdr.dest_ip_address());
302 net_header.set_protocol(goby::acomms::protobuf::NetworkHeader::UDP);
303 net_header.set_srcdest_addr(from_src_dest_pair(std::make_pair(src, dest)));
307 int dest_port = 0, src_port = 0;
308 boost::bimap<int, int>::right_map::const_iterator dest_it =
309 port_map_.right.find(udp_hdr.dest_port());
310 if (dest_it != port_map_.right.end())
312 dest_port = dest_it->second;
316 glog.is(WARN) &&
glog <<
"No mapping for destination UDP port: " << udp_hdr.dest_port()
317 <<
". Unable to send packet." << std::endl;
321 boost::bimap<int, int>::right_map::const_iterator src_it =
322 port_map_.right.find(udp_hdr.source_port());
323 if (src_it != port_map_.right.end())
325 src_port = src_it->second;
330 if (cfg_.total_ports() == cfg_.static_udp_port_size())
332 glog.is(WARN) &&
glog <<
"No mapping for source UDP port: " << udp_hdr.source_port()
333 <<
" and we have no dynamic ports allocated (static_udp_port " 334 "size == total_ports)" 340 boost::bimap<int, int>::left_map::iterator dyn_port_it =
341 port_map_.left.find(dynamic_port_index_);
342 port_map_.left.replace_data(dyn_port_it, udp_hdr.source_port());
343 net_header.mutable_udp()->add_srcdest_port(dynamic_port_index_);
344 ++dynamic_port_index_;
345 if (dynamic_port_index_ >= cfg_.total_ports())
346 dynamic_port_index_ = cfg_.static_udp_port_size();
350 net_header.mutable_udp()->add_srcdest_port(src_port);
351 net_header.mutable_udp()->add_srcdest_port(dest_port);
353 glog.is(VERBOSE) &&
glog <<
"NetHeader: " << net_header.DebugString() << std::endl;
356 dccl_goby_nh_.encode(&nh, net_header);
358 std::map<int, boost::circular_buffer<std::string> >::iterator it = outgoing_.find(dest);
359 if (it == outgoing_.end())
361 std::pair<std::map<int, boost::circular_buffer<std::string> >::iterator,
bool> itboolpair =
363 std::make_pair(dest, boost::circular_buffer<std::string>(cfg_.queue_size())));
364 it = itboolpair.first;
367 it->second.push_back(nh + payload);
373 publish(m,
"Tx" + goby::util::as<std::string>(local_modem_id_));
376 void goby::acomms::IPGateway::receive_packets()
382 FD_SET(tun_fd_, &rd_set);
385 int ret = select(tun_fd_ + 1, &rd_set, 0, 0, &tout);
387 if (ret < 0 && errno != EINTR)
389 glog.is(WARN) &&
glog <<
"Could not select on tun fd." << std::endl;
394 char buffer[ip_mtu_ + 1];
395 int len = read(tun_fd_, buffer, ip_mtu_);
399 glog.is(WARN) &&
glog <<
"tun read error." << std::endl;
403 glog.is(DIE) &&
glog <<
"tun reached EOF." << std::endl;
408 unsigned short ip_header_size = (buffer[0] & 0xF) * 4;
409 unsigned short version = ((buffer[0] >> 4) & 0xF);
412 std::string header_data(buffer, ip_header_size);
413 dccl_ip_.decode(header_data, &ip_hdr);
414 glog.is(DEBUG2) &&
glog <<
"Received " << len <<
" bytes. " << std::endl;
415 switch (ip_hdr.protocol())
418 glog.is(DEBUG1) &&
glog <<
"IPv4 Protocol " << ip_hdr.protocol()
419 <<
" is not supported." << std::endl;
424 std::string udp_header_data(&buffer[ip_header_size], UDP_HEADER_SIZE);
425 dccl_udp_.decode(udp_header_data, &udp_hdr);
426 handle_udp_packet(ip_hdr, udp_hdr,
427 std::string(&buffer[ip_header_size + UDP_HEADER_SIZE],
428 ip_hdr.total_length() - ip_header_size -
435 std::string icmp_header_data(&buffer[ip_header_size], ICMP_HEADER_SIZE);
436 dccl_icmp_.decode(icmp_header_data, &icmp_hdr);
437 glog.is(DEBUG1) &&
glog <<
"Received ICMP Packet with header: " 438 << icmp_hdr.ShortDebugString() << std::endl;
439 glog.is(DEBUG1) &&
glog <<
"ICMP sending is not supported." 458 if (cfg_.has_only_rate() && cfg_.only_rate() != orig_msg.rate())
463 bool had_data =
false;
464 while ((
unsigned)msg.frame_size() < msg.max_num_frames())
468 std::map<int, boost::circular_buffer<std::string> >::iterator it =
469 outgoing_.find(msg.dest());
470 if (it == outgoing_.end())
474 else if (it->second.size() == 0)
480 msg.set_ack_requested(
false);
481 msg.add_frame(it->second.front());
482 it->second.pop_front();
489 for (std::map<
int, boost::circular_buffer<std::string> >::iterator
490 it = outgoing_.begin(),
491 end = outgoing_.end();
494 if (it->second.size() == 0)
500 msg.set_dest(it->first);
501 msg.set_ack_requested(
false);
502 msg.add_frame(it->second.front());
503 it->second.pop_front();
512 publish(msg,
"DataResponse" + goby::util::as<std::string>(local_modem_id_));
517 void goby::acomms::IPGateway::handle_modem_receive(
520 if (cfg_.has_only_rate() && cfg_.only_rate() != modem_msg.rate())
523 for (
int i = 0, n = modem_msg.frame_size(); i < n; ++i)
529 std::string frame = modem_msg.frame(i);
533 dccl_goby_nh_.decode(&frame, &net_header);
537 glog.is(WARN) &&
glog <<
"Could not decode header: " << e.what() << std::endl;
541 glog.is(VERBOSE) &&
glog <<
"NetHeader: " << net_header.DebugString() << std::endl;
543 ip_hdr.set_ihl(MIN_IPV4_HEADER_LENGTH);
544 ip_hdr.set_version(IPV4_VERSION);
547 ip_hdr.set_total_length(MIN_IPV4_HEADER_LENGTH * 4 + UDP_HEADER_SIZE + frame.size());
548 ip_hdr.set_identification(0);
549 ip_hdr.mutable_flags_frag_offset()->set_dont_fragment(
false);
550 ip_hdr.mutable_flags_frag_offset()->set_more_fragments(
false);
551 ip_hdr.mutable_flags_frag_offset()->set_fragment_offset(0);
553 ip_hdr.set_protocol(net_header.protocol());
555 std::pair<int, int> src_dest = to_src_dest_pair(net_header.srcdest_addr());
556 ip_hdr.set_source_ip_address(goby_address_to_ipv4(src_dest.first));
557 ip_hdr.set_dest_ip_address(goby_address_to_ipv4(src_dest.second));
559 if (net_header.udp().srcdest_port_size() == 2)
561 boost::bimap<int, int>::left_map::iterator src_it =
562 port_map_.left.find(net_header.udp().srcdest_port(0));
563 int source_port = src_it->second;
567 int fd = socket(AF_INET, SOCK_DGRAM, 0);
568 struct sockaddr_in addr;
569 memset((
char*)&addr, 0,
sizeof(addr));
570 addr.sin_family = AF_INET;
571 addr.sin_addr.s_addr = htonl(INADDR_ANY);
572 addr.sin_port = htons(0);
573 bind(fd, (
struct sockaddr*)&addr,
sizeof(addr));
575 struct sockaddr_in sa;
578 getsockname(fd, (
struct sockaddr*)&sa, &sa_len);
579 source_port = ntohs(sa.sin_port);
580 dynamic_udp_fd_.push_back(fd);
582 port_map_.left.replace_data(src_it, source_port);
585 boost::bimap<int, int>::left_map::const_iterator dest_it =
586 port_map_.left.find(net_header.udp().srcdest_port(1));
587 int dest_port = dest_it->second;
591 glog <<
"No mapping for destination port: " << net_header.udp().srcdest_port(1)
592 <<
", cannot write packet" << std::endl;
596 udp_hdr.set_source_port(source_port);
597 udp_hdr.set_dest_port(dest_port);
601 glog.is(WARN) &&
glog <<
"Bad srcdest_port field, must have two values." << std::endl;
605 udp_hdr.set_length(UDP_HEADER_SIZE + frame.size());
606 write_udp_packet(ip_hdr, udp_hdr, frame);
612 const std::string& payload)
615 ip_hdr.set_header_checksum(0);
616 udp_hdr.set_checksum(0);
618 std::string ip_hdr_data, udp_hdr_data;
619 dccl_udp_.encode(&udp_hdr_data, udp_hdr);
620 dccl_ip_.encode(&ip_hdr_data, ip_hdr);
629 IPV4_SOURCE_ADDR_OFFSET = 12,
630 IPV4_DEST_ADDR_OFFSET = 16,
635 UDP_LENGTH_OFFSET = 4,
639 std::string udp_pseudo_header = ip_hdr_data.substr(IPV4_SOURCE_ADDR_OFFSET, NET_LONG_BYTES) +
640 ip_hdr_data.substr(IPV4_DEST_ADDR_OFFSET, NET_LONG_BYTES) +
641 char(0) + char(IPPROTO_UDP) +
642 udp_hdr_data.substr(UDP_LENGTH_OFFSET, NET_SHORT_BYTES);
643 assert(udp_pseudo_header.size() == 12);
645 uint16_t ip_checksum = net_checksum(ip_hdr_data);
646 uint16_t udp_checksum = net_checksum(udp_pseudo_header + udp_hdr_data + payload);
648 ip_hdr_data[IPV4_CS_OFFSET] = (ip_checksum >> 8) & 0xFF;
649 ip_hdr_data[IPV4_CS_OFFSET + 1] = ip_checksum & 0xFF;
651 udp_hdr_data[UDP_CS_OFFSET] = (udp_checksum >> 8) & 0xFF;
652 udp_hdr_data[UDP_CS_OFFSET + 1] = udp_checksum & 0xFF;
654 std::string packet(ip_hdr_data + udp_hdr_data + payload);
655 unsigned len = write(tun_fd_, packet.c_str(), packet.size());
656 if (len < packet.size())
657 glog.is(WARN) &&
glog <<
"Failed to write all " << packet.size() <<
" bytes." << std::endl;
660 void goby::acomms::IPGateway::icmp_report_queue()
663 control_msg.set_type(protobuf::IPGatewayICMPControl::QUEUE_REPORT);
664 control_msg.set_address(cfg_.local_ipv4_address());
666 int total_messages = 0;
668 for (std::map<
int, boost::circular_buffer<std::string> >::const_iterator it = outgoing_.begin(),
669 end = outgoing_.end();
672 int size = it->second.size();
676 control_msg.mutable_queue_report()->add_queue();
677 q->set_dest(it->first);
679 total_messages += size;
682 write_icmp_control_message(control_msg);
685 if (total_messages > 0 && cfg_.bypass_mac())
687 if (cfg_.has_bypass_mac_slot())
689 handle_initiate_transmission(cfg_.bypass_mac_slot());
694 m.set_src(local_modem_id_);
695 m.set_type(protobuf::ModemTransmission::DATA);
696 if (cfg_.has_only_rate())
697 m.set_rate(cfg_.only_rate());
698 handle_initiate_transmission(m);
703 void goby::acomms::IPGateway::write_icmp_control_message(
706 std::string control_data;
707 control_msg.SerializeToString(&control_data);
709 glog.is(DEBUG1) &&
glog <<
"Writing ICMP Control message: " << control_msg.DebugString()
713 ip_hdr.set_ihl(MIN_IPV4_HEADER_LENGTH);
714 ip_hdr.set_version(IPV4_VERSION);
717 ip_hdr.set_total_length(MIN_IPV4_HEADER_LENGTH * 4 + ICMP_HEADER_SIZE + control_data.size());
718 ip_hdr.set_identification(0);
719 ip_hdr.mutable_flags_frag_offset()->set_dont_fragment(
false);
720 ip_hdr.mutable_flags_frag_offset()->set_more_fragments(
false);
721 ip_hdr.mutable_flags_frag_offset()->set_fragment_offset(0);
723 ip_hdr.set_protocol(IPPROTO_ICMP);
724 ip_hdr.set_source_ip_address(cfg_.local_ipv4_address());
725 ip_hdr.set_dest_ip_address(cfg_.local_ipv4_address());
728 icmp_hdr.set_type(ICMP_TYPE);
729 icmp_hdr.set_code(ICMP_CODE);
731 write_icmp_packet(ip_hdr, icmp_hdr, control_data);
736 const std::string& payload)
739 ip_hdr.set_header_checksum(0);
740 icmp_hdr.set_checksum(0);
741 icmp_hdr.set_short1(0);
742 icmp_hdr.set_short2(0);
744 std::string ip_hdr_data, icmp_hdr_data;
745 dccl_icmp_.encode(&icmp_hdr_data, icmp_hdr);
746 dccl_ip_.encode(&ip_hdr_data, ip_hdr);
755 IPV4_SOURCE_ADDR_OFFSET = 12,
756 IPV4_DEST_ADDR_OFFSET = 16,
764 uint16_t ip_checksum = net_checksum(ip_hdr_data);
765 uint16_t icmp_checksum = net_checksum(icmp_hdr_data + payload);
767 ip_hdr_data[IPV4_CS_OFFSET] = (ip_checksum >> 8) & 0xFF;
768 ip_hdr_data[IPV4_CS_OFFSET + 1] = ip_checksum & 0xFF;
770 icmp_hdr_data[ICMP_CS_OFFSET] = (icmp_checksum >> 8) & 0xFF;
771 icmp_hdr_data[ICMP_CS_OFFSET + 1] = icmp_checksum & 0xFF;
773 std::string packet(ip_hdr_data + icmp_hdr_data + payload);
774 unsigned len = write(tun_fd_, packet.c_str(), packet.size());
775 if (len < packet.size())
776 glog.is(WARN) &&
glog <<
"Failed to write all " << packet.size() <<
" bytes." << std::endl;
786 std::pair<int, int> goby::acomms::IPGateway::to_src_dest_pair(
int srcdest)
788 int src = (srcdest - 1) % (total_addresses_ - 2) + 1;
789 int dest = (srcdest - 1) / (total_addresses_ - 2);
793 return std::make_pair(src, dest);
796 int goby::acomms::IPGateway::from_src_dest_pair(std::pair<int, int> src_dest)
798 int src = src_dest.first;
799 int dest = src_dest.second;
804 return dest * (total_addresses_ - 2) + src - (src > dest ? 1 : 0);
807 int goby::acomms::IPGateway::ipv4_to_goby_address(
const std::string& ipv4_address)
810 inet_aton(ipv4_address.c_str(), &remote_addr);
811 goby::uint32 remote_address = ntohl(remote_addr.s_addr);
812 int modem_id = remote_address & ~netmask_;
815 if (modem_id + netmask_ == 0xFFFFFFFF)
820 std::string goby::acomms::IPGateway::goby_address_to_ipv4(
int modem_id)
824 address = (local_address_ & netmask_) + ~netmask_;
826 address = (local_address_ & netmask_) + modem_id;
829 ret_addr.s_addr = htonl(address);
830 return std::string(inet_ntoa(ret_addr));
833 int goby::acomms::IPGateway::ac_freq(
int srcdest)
835 std::pair<int, int> sd = to_src_dest_pair(srcdest);
838 int N = total_addresses_ + 1;
839 const int scale_factor = N * N * 100;
841 double p0 = 1.0 / (N - 2);
842 double p1 = 1.0 / (N - 3);
843 double p2 = 1.0 / (N * N - 6 * N + 9);
847 else if (s == cfg_.gateway_id())
848 return scale_factor * p0 * (1 - cfg_.gamma_autonomy());
849 else if (d == cfg_.gateway_id())
850 return scale_factor * p1 * (cfg_.gamma_autonomy() - cfg_.gamma_collaboration());
852 return scale_factor * p2 * (cfg_.gamma_collaboration());
855 int main(
int argc,
char* argv[])
857 dccl::FieldCodecManager::add<goby::acomms::IPGatewayEmptyIdentifierCodec<0xF000> >(
858 "ip_gateway_id_codec_0");
859 dccl::FieldCodecManager::add<goby::acomms::IPGatewayEmptyIdentifierCodec<0xF001> >(
860 "ip_gateway_id_codec_1");
861 dccl::FieldCodecManager::add<goby::acomms::IPGatewayEmptyIdentifierCodec<0xF002> >(
862 "ip_gateway_id_codec_2");
863 dccl::FieldCodecManager::add<goby::acomms::IPGatewayEmptyIdentifierCodec<0xF003> >(
864 "ip_gateway_id_codec_3");
865 dccl::FieldCodecManager::add<goby::acomms::NetShortCodec>(
"net.short");
866 dccl::FieldCodecManager::add<goby::acomms::IPv4AddressCodec>(
"ip.v4.address");
867 dccl::FieldCodecManager::add<goby::acomms::IPv4FlagsFragOffsetCodec>(
"ip.v4.flagsfragoffset");
870 goby::run<goby::acomms::IPGateway>(argc, argv, &cfg);
878 int tun_alloc(
char* dev)
883 if ((fd = open(
"/dev/net/tun", O_RDWR)) < 0)
886 memset(&ifr, 0,
sizeof(ifr));
893 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
895 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
897 if ((err = ioctl(fd, TUNSETIFF, (
void*)&ifr)) < 0)
903 strcpy(dev, ifr.ifr_name);
908 int tun_config(
const char* dev,
const char* host,
unsigned cidr_prefix,
unsigned mtu)
913 struct sockaddr_in* sai = (
struct sockaddr_in*)&ifr.ifr_addr;
916 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
918 memset(&ifr, 0,
sizeof(ifr));
920 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
922 sai->sin_family = AF_INET;
925 int ret = inet_aton(host, &sai->sin_addr);
929 if (ioctl(sockfd, SIOCSIFADDR, &ifr) == -1)
932 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) == -1)
937 if (ioctl(sockfd, SIOCSIFMTU, &ifr) == -1)
940 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
942 if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) == -1)
947 struct ifreq ifr_mask;
948 struct sockaddr_in* sai_mask = (
struct sockaddr_in*)&ifr_mask.ifr_addr;
949 memset(&ifr_mask, 0,
sizeof(ifr_mask));
950 strncpy(ifr_mask.ifr_name, dev, IFNAMSIZ);
952 sai_mask->sin_family = AF_INET;
953 sai_mask->sin_port = 0;
955 if (cidr_prefix > IPV4_ADDRESS_BITS)
958 sai_mask->sin_addr.s_addr = htonl(0xFFFFFFFF - ((1 << (IPV4_ADDRESS_BITS - cidr_prefix)) - 1));
960 if (ioctl(sockfd, SIOCSIFNETMASK, &ifr_mask) == -1)
Base class provided for users to generate applications that participate in the Goby publish/subscribe...
void set_name(const std::string &s)
Set the name of the application that the logger is serving.
void startup(const protobuf::MACConfig &cfg)
Starts the MAC with given configuration.
google::protobuf::uint32 uint32
an unsigned 32 bit integer
void do_work()
Allows the MAC timer to do its work. Does not block. If you prefer more control you can directly cont...
const int BROADCAST_ID
special modem id for the broadcast destination - no one is assigned this address. Analogous to 192...
provides an API to the goby-acomms MAC library. MACManager is essentially a std::list<protobuf::Modem...
void connect(Signal *signal, Slot slot)
connect a signal to a slot (e.g. function pointer)
common::FlexOstream glog
Access the Goby logger through this object.
The global namespace for the Goby project.
boost::signals2::signal< void(const protobuf::ModemTransmission &m)> signal_initiate_transmission
Signals when it is time for this platform to begin transmission of an acoustic message at the start o...
void bind(ModemDriverBase &driver, QueueManager &queue_manager)
binds the driver link-layer callbacks to the QueueManager
simple exception class for goby applications
const int QUERY_DESTINATION_ID
special modem id used internally to goby-acomms for indicating that the MAC layer (amac) is agnostic ...