diff --git a/repos/os/src/server/nic_router/dhcp_client.cc b/repos/os/src/server/nic_router/dhcp_client.cc index 4be9382776..fff79d39ca 100644 --- a/repos/os/src/server/nic_router/dhcp_client.cc +++ b/repos/os/src/server/nic_router/dhcp_client.cc @@ -168,97 +168,91 @@ void Dhcp_client::_send(Message_type msg_type, Ipv4_address client_ip, Ipv4_address server_ip) { - /* allocate buffer for the request */ - enum { BUF_SIZE = 1024 }; - using Size_guard = Size_guard_tpl; - void *buf; - try { _alloc.alloc(BUF_SIZE, &buf); } - catch (...) { throw Interface::Alloc_dhcp_msg_buffer_failed(); } + enum { PKT_SIZE = 1024 }; + using Size_guard = Size_guard_tpl; Mac_address client_mac = _interface.router_mac(); + _interface.send(PKT_SIZE, [&] (void *pkt_base) { - /* create ETH header of the request */ - Size_guard size; - size.add(sizeof(Ethernet_frame)); - Ethernet_frame ð = *reinterpret_cast(buf); - eth.dst(Mac_address(0xff)); - eth.src(client_mac); - eth.type(Ethernet_frame::Type::IPV4); + /* create ETH header of the request */ + Size_guard size; + size.add(sizeof(Ethernet_frame)); + Ethernet_frame ð = *reinterpret_cast(pkt_base); + eth.dst(Mac_address(0xff)); + eth.src(client_mac); + eth.type(Ethernet_frame::Type::IPV4); - /* create IP header of the request */ - enum { IPV4_TIME_TO_LIVE = 64 }; - size_t const ip_off = size.curr(); - size.add(sizeof(Ipv4_packet)); - Ipv4_packet &ip = *eth.data(); - ip.header_length(sizeof(Ipv4_packet) / 4); - ip.version(4); - ip.diff_service(0); - ip.identification(0); - ip.flags(0); - ip.fragment_offset(0); - ip.time_to_live(IPV4_TIME_TO_LIVE); - ip.protocol(Ipv4_packet::Protocol::UDP); - ip.src(client_ip); - ip.dst(Ipv4_address(0xff)); + /* create IP header of the request */ + enum { IPV4_TIME_TO_LIVE = 64 }; + size_t const ip_off = size.curr(); + size.add(sizeof(Ipv4_packet)); + Ipv4_packet &ip = *eth.data(); + ip.header_length(sizeof(Ipv4_packet) / 4); + ip.version(4); + ip.diff_service(0); + ip.identification(0); + ip.flags(0); + ip.fragment_offset(0); + ip.time_to_live(IPV4_TIME_TO_LIVE); + ip.protocol(Ipv4_packet::Protocol::UDP); + ip.src(client_ip); + ip.dst(Ipv4_address(0xff)); - /* create UDP header of the request */ - size_t const udp_off = size.curr(); - size.add(sizeof(Udp_packet)); - Udp_packet &udp = *ip.data(); - udp.src_port(Port(Dhcp_packet::BOOTPC)); - udp.dst_port(Port(Dhcp_packet::BOOTPS)); + /* create UDP header of the request */ + size_t const udp_off = size.curr(); + size.add(sizeof(Udp_packet)); + Udp_packet &udp = *ip.data(); + udp.src_port(Port(Dhcp_packet::BOOTPC)); + udp.dst_port(Port(Dhcp_packet::BOOTPS)); - /* create mandatory DHCP fields of the request */ - size_t const dhcp_off = size.curr(); - size.add(sizeof(Dhcp_packet)); - Dhcp_packet &dhcp = *udp.data(); - dhcp.op(Dhcp_packet::REQUEST); - dhcp.htype(Dhcp_packet::Htype::ETH); - dhcp.hlen(sizeof(Mac_address)); - dhcp.hops(0); - dhcp.xid(0x12345678); - dhcp.secs(0); - dhcp.flags(0); - dhcp.ciaddr(client_ip); - dhcp.yiaddr(Ipv4_address()); - dhcp.siaddr(Ipv4_address()); - dhcp.giaddr(Ipv4_address()); - dhcp.client_mac(client_mac); - dhcp.zero_fill_sname(); - dhcp.zero_fill_file(); - dhcp.default_magic_cookie(); + /* create mandatory DHCP fields of the request */ + size_t const dhcp_off = size.curr(); + size.add(sizeof(Dhcp_packet)); + Dhcp_packet &dhcp = *udp.data(); + dhcp.op(Dhcp_packet::REQUEST); + dhcp.htype(Dhcp_packet::Htype::ETH); + dhcp.hlen(sizeof(Mac_address)); + dhcp.hops(0); + dhcp.xid(0x12345678); + dhcp.secs(0); + dhcp.flags(0); + dhcp.ciaddr(client_ip); + dhcp.yiaddr(Ipv4_address()); + dhcp.siaddr(Ipv4_address()); + dhcp.giaddr(Ipv4_address()); + dhcp.client_mac(client_mac); + dhcp.zero_fill_sname(); + dhcp.zero_fill_file(); + dhcp.default_magic_cookie(); - /* append DHCP option fields to the request */ - Dhcp_packet::Options_aggregator - dhcp_opts(dhcp, size); - dhcp_opts.append_option(msg_type); + /* append DHCP option fields to the request */ + Dhcp_packet::Options_aggregator + dhcp_opts(dhcp, size); + dhcp_opts.append_option(msg_type); - switch (msg_type) { - case Message_type::DISCOVER: - dhcp_opts.append_option(client_mac); - dhcp_opts.append_option(BUF_SIZE - dhcp_off); - break; + switch (msg_type) { + case Message_type::DISCOVER: + dhcp_opts.append_option(client_mac); + dhcp_opts.append_option(PKT_SIZE - dhcp_off); + break; - case Message_type::REQUEST: - dhcp_opts.append_option(client_mac); - dhcp_opts.append_option(BUF_SIZE - dhcp_off); - if (_state == State::REQUEST) { - dhcp_opts.append_option(client_ip); - dhcp_opts.append_option(server_ip); + case Message_type::REQUEST: + dhcp_opts.append_option(client_mac); + dhcp_opts.append_option(PKT_SIZE - dhcp_off); + if (_state == State::REQUEST) { + dhcp_opts.append_option(client_ip); + dhcp_opts.append_option(server_ip); + } + break; + + default: + throw Interface::Bad_send_dhcp_args(); } - break; + dhcp_opts.append_option(); - default: - throw Interface::Bad_send_dhcp_args(); - } - dhcp_opts.append_option(); - - /* fill in header values that need the packet to be complete already */ - udp.length(size.curr() - udp_off); - udp.update_checksum(ip.src(), ip.dst()); - ip.total_length(size.curr() - ip_off); - ip.checksum(Ipv4_packet::calculate_checksum(ip)); - - /* send request to sender of request and free request buffer */ - _interface.send(eth, size.curr()); - _alloc.free(buf, BUF_SIZE); + /* fill in header values that need the packet to be complete already */ + udp.length(size.curr() - udp_off); + udp.update_checksum(ip.src(), ip.dst()); + ip.total_length(size.curr() - ip_off); + ip.checksum(Ipv4_packet::calculate_checksum(ip)); + }); } diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index fd7cb76157..f40c812635 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -291,84 +291,78 @@ void Interface::_send_dhcp_reply(Dhcp_server const &dhcp_srv, Dhcp_packet::Message_type msg_type, uint32_t xid) { - /* allocate buffer for the reply */ - enum { BUF_SIZE = 512 }; - using Size_guard = Size_guard_tpl; - void *buf; - try { _alloc.alloc(BUF_SIZE, &buf); } - catch (...) { throw Alloc_dhcp_msg_buffer_failed(); } + enum { PKT_SIZE = 512 }; + using Size_guard = Size_guard_tpl; + send(PKT_SIZE, [&] (void *pkt_base) { - /* create ETH header of the reply */ - Size_guard size; - size.add(sizeof(Ethernet_frame)); - Ethernet_frame ð = *reinterpret_cast(buf); - eth.dst(client_mac); - eth.src(_router_mac); - eth.type(Ethernet_frame::Type::IPV4); + /* create ETH header of the reply */ + Size_guard size; + size.add(sizeof(Ethernet_frame)); + Ethernet_frame ð = *reinterpret_cast(pkt_base); + eth.dst(client_mac); + eth.src(_router_mac); + eth.type(Ethernet_frame::Type::IPV4); - /* create IP header of the reply */ - enum { IPV4_TIME_TO_LIVE = 64 }; - size_t const ip_off = size.curr(); - size.add(sizeof(Ipv4_packet)); - Ipv4_packet &ip = *eth.data(); - ip.header_length(sizeof(Ipv4_packet) / 4); - ip.version(4); - ip.diff_service(0); - ip.identification(0); - ip.flags(0); - ip.fragment_offset(0); - ip.time_to_live(IPV4_TIME_TO_LIVE); - ip.protocol(Ipv4_packet::Protocol::UDP); - ip.src(_router_ip()); - ip.dst(client_ip); + /* create IP header of the reply */ + enum { IPV4_TIME_TO_LIVE = 64 }; + size_t const ip_off = size.curr(); + size.add(sizeof(Ipv4_packet)); + Ipv4_packet &ip = *eth.data(); + ip.header_length(sizeof(Ipv4_packet) / 4); + ip.version(4); + ip.diff_service(0); + ip.identification(0); + ip.flags(0); + ip.fragment_offset(0); + ip.time_to_live(IPV4_TIME_TO_LIVE); + ip.protocol(Ipv4_packet::Protocol::UDP); + ip.src(_router_ip()); + ip.dst(client_ip); - /* create UDP header of the reply */ - size_t const udp_off = size.curr(); - size.add(sizeof(Udp_packet)); - Udp_packet &udp = *ip.data(); - udp.src_port(Port(Dhcp_packet::BOOTPS)); - udp.dst_port(Port(Dhcp_packet::BOOTPC)); + /* create UDP header of the reply */ + size_t const udp_off = size.curr(); + size.add(sizeof(Udp_packet)); + Udp_packet &udp = *ip.data(); + udp.src_port(Port(Dhcp_packet::BOOTPS)); + udp.dst_port(Port(Dhcp_packet::BOOTPC)); - /* create mandatory DHCP fields of the reply */ - size.add(sizeof(Dhcp_packet)); - Dhcp_packet &dhcp = *udp.data(); - dhcp.op(Dhcp_packet::REPLY); - dhcp.htype(Dhcp_packet::Htype::ETH); - dhcp.hlen(sizeof(Mac_address)); - dhcp.hops(0); - dhcp.xid(xid); - dhcp.secs(0); - dhcp.flags(0); - dhcp.ciaddr(msg_type == Dhcp_packet::Message_type::INFORM ? client_ip : Ipv4_address()); - dhcp.yiaddr(msg_type == Dhcp_packet::Message_type::INFORM ? Ipv4_address() : client_ip); - dhcp.siaddr(_router_ip()); - dhcp.giaddr(Ipv4_address()); - dhcp.client_mac(client_mac); - dhcp.zero_fill_sname(); - dhcp.zero_fill_file(); - dhcp.default_magic_cookie(); + /* create mandatory DHCP fields of the reply */ + size.add(sizeof(Dhcp_packet)); + Dhcp_packet &dhcp = *udp.data(); + dhcp.op(Dhcp_packet::REPLY); + dhcp.htype(Dhcp_packet::Htype::ETH); + dhcp.hlen(sizeof(Mac_address)); + dhcp.hops(0); + dhcp.xid(xid); + dhcp.secs(0); + dhcp.flags(0); + dhcp.ciaddr(msg_type == Dhcp_packet::Message_type::INFORM ? client_ip : Ipv4_address()); + dhcp.yiaddr(msg_type == Dhcp_packet::Message_type::INFORM ? Ipv4_address() : client_ip); + dhcp.siaddr(_router_ip()); + dhcp.giaddr(Ipv4_address()); + dhcp.client_mac(client_mac); + dhcp.zero_fill_sname(); + dhcp.zero_fill_file(); + dhcp.default_magic_cookie(); - /* append DHCP option fields to the reply */ - Dhcp_packet::Options_aggregator dhcp_opts(dhcp, size); - dhcp_opts.append_option(msg_type); - dhcp_opts.append_option(_router_ip()); - dhcp_opts.append_option(dhcp_srv.ip_lease_time().value / 1000 / 1000); - dhcp_opts.append_option(_ip_config().interface.subnet_mask()); - dhcp_opts.append_option(_router_ip()); - if (dhcp_srv.dns_server().valid()) { - dhcp_opts.append_option(dhcp_srv.dns_server()); } - dhcp_opts.append_option(_ip_config().interface.broadcast_address()); - dhcp_opts.append_option(); + /* append DHCP option fields to the reply */ + Dhcp_packet::Options_aggregator dhcp_opts(dhcp, size); + dhcp_opts.append_option(msg_type); + dhcp_opts.append_option(_router_ip()); + dhcp_opts.append_option(dhcp_srv.ip_lease_time().value / 1000 / 1000); + dhcp_opts.append_option(_ip_config().interface.subnet_mask()); + dhcp_opts.append_option(_router_ip()); + if (dhcp_srv.dns_server().valid()) { + dhcp_opts.append_option(dhcp_srv.dns_server()); } + dhcp_opts.append_option(_ip_config().interface.broadcast_address()); + dhcp_opts.append_option(); - /* fill in header values that need the packet to be complete already */ - udp.length(size.curr() - udp_off); - udp.update_checksum(ip.src(), ip.dst()); - ip.total_length(size.curr() - ip_off); - ip.checksum(Ipv4_packet::calculate_checksum(ip)); - - /* send reply to sender of request and free reply buffer */ - send(eth, size.curr()); - _alloc.free(buf, BUF_SIZE); + /* fill in header values that need the packet to be complete already */ + udp.length(size.curr() - udp_off); + udp.update_checksum(ip.src(), ip.dst()); + ip.total_length(size.curr() - ip_off); + ip.checksum(Ipv4_packet::calculate_checksum(ip)); + }); } @@ -675,19 +669,34 @@ void Interface::_handle_ip(Ethernet_frame ð, void Interface::_broadcast_arp_request(Ipv4_address const &ip) { - Ethernet_frame_sized - eth(Mac_address(0xff), _router_mac, Ethernet_frame::Type::ARP); - Arp_packet &arp = *eth.data(); - arp.hardware_address_type(Arp_packet::ETHERNET); - arp.protocol_address_type(Arp_packet::IPV4); - arp.hardware_address_size(sizeof(Mac_address)); - arp.protocol_address_size(sizeof(Ipv4_address)); - arp.opcode(Arp_packet::REQUEST); - arp.src_mac(_router_mac); - arp.src_ip(_router_ip()); - arp.dst_mac(Mac_address(0xff)); - arp.dst_ip(ip); - send(eth, sizeof(eth)); + enum { + ETH_HDR_SZ = sizeof(Ethernet_frame), + ETH_DAT_SZ = sizeof(Arp_packet) + ETH_HDR_SZ >= Ethernet_frame::MIN_SIZE ? + sizeof(Arp_packet) : + Ethernet_frame::MIN_SIZE - ETH_HDR_SZ, + ETH_CRC_SZ = sizeof(Genode::uint32_t), + PKT_SIZE = ETH_HDR_SZ + ETH_DAT_SZ + ETH_CRC_SZ, + }; + send(PKT_SIZE, [&] (void *pkt_base) { + + /* write Ethernet header */ + Ethernet_frame ð = *reinterpret_cast(pkt_base); + eth.dst(Mac_address(0xff)); + eth.src(_router_mac); + eth.type(Ethernet_frame::Type::ARP); + + /* write ARP header */ + Arp_packet &arp = *eth.data(); + arp.hardware_address_type(Arp_packet::ETHERNET); + arp.protocol_address_type(Arp_packet::IPV4); + arp.hardware_address_size(sizeof(Mac_address)); + arp.protocol_address_size(sizeof(Ipv4_address)); + arp.opcode(Arp_packet::REQUEST); + arp.src_mac(_router_mac); + arp.src_ip(_router_ip()); + arp.dst_mac(Mac_address(0xff)); + arp.dst_ip(ip); + }); }