status_t arp_init_protocol(net_interface* interface, net_domain* domain, net_datalink_protocol** _protocol) { // We currently only support a single family and type! if (interface->device->type != IFT_ETHER || domain->family != AF_INET) return B_BAD_TYPE; status_t status = sStackModule->register_device_handler(interface->device, B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_ARP), &arp_receive, NULL); if (status != B_OK) return status; status = sStackModule->register_domain_device_handler( interface->device, B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_IP), domain); if (status != B_OK) return status; arp_protocol* protocol = new(std::nothrow) arp_protocol; if (protocol == NULL) return B_NO_MEMORY; memset(&protocol->hardware_address, 0, sizeof(sockaddr_dl)); protocol->local_address = 0; *_protocol = protocol; return B_OK; }
status_t arp_uninit_protocol(net_datalink_protocol *protocol) { sStackModule->unregister_device_handler(protocol->interface->device, B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_ARP)); sStackModule->unregister_device_handler(protocol->interface->device, B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_IP)); delete protocol; return B_OK; }
int32 ethernet_deframe(net_device* device, net_buffer* buffer) { //dprintf("asked to deframe buffer for device %s\n", device->name); NetBufferHeaderRemover<ether_header> bufferHeader(buffer); if (bufferHeader.Status() != B_OK) return bufferHeader.Status(); ether_header& header = bufferHeader.Data(); uint16 type = B_BENDIAN_TO_HOST_INT16(header.type); struct sockaddr_dl& source = *(struct sockaddr_dl*)buffer->source; struct sockaddr_dl& destination = *(struct sockaddr_dl*)buffer->destination; source.sdl_len = sizeof(sockaddr_dl); source.sdl_family = AF_LINK; source.sdl_index = device->index; source.sdl_type = IFT_ETHER; source.sdl_e_type = header.type; source.sdl_nlen = source.sdl_slen = 0; source.sdl_alen = ETHER_ADDRESS_LENGTH; memcpy(source.sdl_data, header.source, ETHER_ADDRESS_LENGTH); destination.sdl_len = sizeof(sockaddr_dl); destination.sdl_family = AF_LINK; destination.sdl_index = device->index; destination.sdl_type = IFT_ETHER; destination.sdl_e_type = header.type; destination.sdl_nlen = destination.sdl_slen = 0; destination.sdl_alen = ETHER_ADDRESS_LENGTH; memcpy(destination.sdl_data, header.destination, ETHER_ADDRESS_LENGTH); // Mark buffer if it was a broadcast/multicast packet if (!memcmp(header.destination, kBroadcastAddress, ETHER_ADDRESS_LENGTH)) buffer->flags |= MSG_BCAST; else if ((header.destination[0] & 0x01) != 0) buffer->flags |= MSG_MCAST; // Translate the ethernet specific type to a generic one if possible switch (type) { case ETHER_TYPE_IP: buffer->type = B_NET_FRAME_TYPE_IPV4; break; case ETHER_TYPE_IPV6: buffer->type = B_NET_FRAME_TYPE_IPV6; break; case ETHER_TYPE_IPX: buffer->type = B_NET_FRAME_TYPE_IPX; break; default: buffer->type = B_NET_FRAME_TYPE(IFT_ETHER, type); break; } return B_OK; }
status_t ppp_frame_init(struct net_interface* interface, net_domain* domain, net_datalink_protocol** _protocol) { // We only support a single type! dprintf("in function: %s::%s\n", __FILE__, __func__); if (interface->device->type != IFT_PPP) return B_BAD_TYPE; ppp_frame_protocol* protocol; status_t status = sStackModule->register_device_deframer(interface->device, &ppp_deframe); if (status != B_OK) return status; status = sStackModule->register_domain_device_handler( interface->device, B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_PPPOE), domain); if (status != B_OK) return status; status = sStackModule->register_domain_device_handler( interface->device, B_NET_FRAME_TYPE_IPV4, domain); if (status != B_OK) return status; // Locally received buffers don't need a domain device handler, as the // buffer reception is handled internally. protocol = new(std::nothrow) ppp_frame_protocol; if (protocol == NULL) { sStackModule->unregister_device_deframer(interface->device); return B_NO_MEMORY; } *_protocol = protocol; return B_OK; }
status_t pppoe_input(void *cookie, net_device *_device, net_buffer *packet) { if (!packet) return B_ERROR; NetBufferHeaderReader<pppoe_header> bufferheader(packet); if (bufferheader.Status() != B_OK) return B_ERROR; pppoe_header &header = bufferheader.Data(); // remove the following lines when pppoe server is enabled if (header.code == PADI) { TRACE("PADI packet received, ignoreing!\n"); gBufferModule->free(packet); return B_OK; } if (header.code == PADO || header.code == PADR || header.code == PADS || header.code == PADT) { uint8 peerEtherAddr[ETHER_ADDRESS_LENGTH]; struct sockaddr_dl& source = *(struct sockaddr_dl*)packet->source; memcpy(peerEtherAddr, source.sdl_data, ETHER_ADDRESS_LENGTH); const char *str = header.code == PADI ? "PADI" : header.code == PADO ? "PADO" : header.code == PADR ? "PADR" : header.code == PADS ? "PADS" : "PADT" ; dprintf("%s from:%02x:%02x:%02x:%02x:%02x:%02x code:%02x\n", str, peerEtherAddr[0], peerEtherAddr[1], peerEtherAddr[2], peerEtherAddr[3], peerEtherAddr[4], peerEtherAddr[5], header.code); } PPPoEDevice *device; pppoe_query *query; sockaddr_dl& linkAddress = *(sockaddr_dl*)packet->source; int32 specificType = B_NET_FRAME_TYPE(linkAddress.sdl_type, ntohs(linkAddress.sdl_e_type)); // MutexLocker locker(sLock); if (specificType == B_NET_FRAME_TYPE_PPPOE_DISCOVERY && ntohs(header.length) <= PPPoE_QUERY_REPORT_SIZE) { for (int32 index = 0; index < sDevices->CountItems(); index++) { query = sQueries->ItemAt(index); if (query) {// && query->ethernetIfnet == sourceIfnet) { if (header.code == PADO) { DiscoveryPacket discovery(packet, ETHER_HDR_LEN); if (discovery.InitCheck() != B_OK) { ERROR("PPPoE: received corrupted discovery packet!\n"); // gBufferModule->free(packet); return B_ERROR; } pppoe_tag *hostTag = discovery.TagWithType(HOST_UNIQ); if (hostTag && hostTag->length == 4 && *((uint32*)hostTag->data) == query->hostUniq) { SendQueryPacket(query, discovery); // gBufferModule->free(packet); return B_ERROR; } } } } } TRACE("in pppoed processing sDevices->CountItems(): %ld\n", sDevices->CountItems()); for (int32 index = 0; index < sDevices->CountItems(); index++) { device = sDevices->ItemAt(index); TRACE("device->SessionID() %d, header.sessionID: %d\n", device->SessionID(), header.sessionID); if (device) { // && device->EthernetIfnet() == sourceIfnet) { if (specificType == B_NET_FRAME_TYPE_PPPOE && header.sessionID == device->SessionID()) { TRACE("PPPoE: session packet\n"); device->Receive(packet); return B_OK; } if (specificType == B_NET_FRAME_TYPE_PPPOE_DISCOVERY && header.code != PADI && header.code != PADR && !device->IsDown()) { TRACE("PPPoE: discovery packet\n"); DiscoveryPacket discovery(packet, ETHER_HDR_LEN); if (discovery.InitCheck() != B_OK) { ERROR("PPPoE: received corrupted discovery packet!\n"); gBufferModule->free(packet); return B_OK; } pppoe_tag *tag = discovery.TagWithType(HOST_UNIQ); if (header.code == PADT || (tag && tag->length == 4 && *((uint32*)tag->data) == device->HostUniq())) { device->Receive(packet); return B_OK; } } } } ERROR("PPPoE: No device found for packet from: %s\n", "ethernet"); // gBufferModule->free(packet); return B_ERROR; }