/*! Checks if an interface is valid, that is, if it has an address in any family, and, in case of ethernet, a hardware MAC address. */ bool NetServer::_IsValidInterface(int socket, const char* name) { ifreq request; if (!prepare_request(request, name)) return B_ERROR; // check if it has an address int32 addresses = 0; for (int32 i = 0; kFamilies[i].family >= 0; i++) { int familySocket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0); if (familySocket < 0) continue; if (ioctl(familySocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) { if (request.ifr_addr.sa_family == kFamilies[i].family) addresses++; } close(familySocket); } if (addresses == 0) return false; // check if it has a hardware address, too, in case of ethernet if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0) return false; int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0); if (linkSocket < 0) return false; prepare_request(request, request.ifr_parameter.device); if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) { close(linkSocket); return false; } close(linkSocket); sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr; if (link.sdl_type == IFT_ETHER && link.sdl_alen < 6) return false; return true; }
status_t NetServer::_DisableInterface(int socket, const char* name) { ifreq request; if (!prepare_request(request, name)) return B_ERROR; if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Getting flags failed: %s\n", Name(), strerror(errno)); return B_ERROR; } // Set interface down request.ifr_flags &= ~(IFF_UP | IFF_AUTO_CONFIGURED | IFF_CONFIGURING); if (ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno)); return B_ERROR; } fprintf(stderr, "%s: set %s interface down...\n", Name(), name); return B_OK; }
status_t get_mac_address(const char* device, uint8* address) { int socket = ::socket(AF_LINK, SOCK_DGRAM, 0); if (socket < 0) return errno; ifreq request; if (!prepare_request(request, device)) { close(socket); return B_ERROR; } if (ioctl(socket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) { close(socket); return errno; } close(socket); sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr; if (link.sdl_type != IFT_ETHER) return B_BAD_TYPE; if (link.sdl_alen == 0) return B_ENTRY_NOT_FOUND; uint8 *mac = (uint8 *)LLADDR(&link); memcpy(address, mac, 6); return B_OK; }
void NetServer::_HandleDeviceMonitor(int socket, BMessage* message) { int32 opcode; if (message->FindInt32("opcode", &opcode) != B_OK || (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED)) return; const char* path; const char* watchedPath; if (message->FindString("watched_path", &watchedPath) != B_OK || message->FindString("path", &path) != B_OK) return; if (opcode == B_ENTRY_CREATED) _ConfigureDevice(socket, path); else { ifreq request; if (!prepare_request(request, path)) return; if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not delete interface %s: %s\n", Name(), path, strerror(errno)); } } }
Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) { Error err = prepare_request(p_method, p_url, p_headers); if (err != OK) return err; godot_xhr_send_string(xhr_id, p_body.utf8().get_data()); return OK; }
Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) { Error err = prepare_request(p_method, p_url, p_headers); if (err != OK) return err; PoolByteArray::Read read = p_body.read(); godot_xhr_send_data(xhr_id, read.ptr(), p_body.size()); return OK; }
void delete_interface(int socket, const char* name) { ifreq request; if (!prepare_request(request, name)) return; if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not delete interface %s: %s\n", kProgramName, name, strerror(errno)); } }
void delete_route(int socket, const char *interface, route_entry &route) { ifreq request; if (!prepare_request(request, interface)) return; request.ifr_route = route; if (ioctl(socket, SIOCDELRT, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not delete route for %s: %s\n", kProgramName, interface, strerror(errno)); } }
void NetServer::_RemoveInvalidInterfaces(int socket) { // get a list of all interfaces ifconf config; config.ifc_len = sizeof(config.ifc_value); if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) return; uint32 count = (uint32)config.ifc_value; if (count == 0) { // there are no interfaces yet return; } void *buffer = malloc(count * sizeof(struct ifreq)); if (buffer == NULL) { fprintf(stderr, "%s: Out of memory.\n", Name()); return; } config.ifc_len = count * sizeof(struct ifreq); config.ifc_buf = buffer; if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) { free(buffer); return; } ifreq *interface = (ifreq *)buffer; for (uint32 i = 0; i < count; i++) { if (!_IsValidInterface(socket, interface->ifr_name)) { // remove invalid interface ifreq request; if (!prepare_request(request, interface->ifr_name)) break; if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not delete interface %s: %s\n", Name(), interface->ifr_name, strerror(errno)); } } interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + interface->ifr_addr.sa_len); } free(buffer); }
status_t NetServer::_RemoveInterface(int socket, const char* name) { ifreq request; if (!prepare_request(request, name)) return B_ERROR; if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not delete interface %s: %s\n", Name(), name, strerror(errno)); return B_ERROR; } return B_OK; }
static int pcap_stats_haiku(pcap_t *handle, struct pcap_stat *stats) { ifreq request; prepare_request(request, handle->md.device); if (ioctl(handle->fd, SIOCGIFSTATS, &request, sizeof(struct ifreq)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s", strerror(errno)); return -1; } handle->md.stat.ps_recv += request.ifr_stats.receive.packets; handle->md.stat.ps_drop += request.ifr_stats.receive.dropped; *stats = handle->md.stat; return 0; }
static int pcap_stats_haiku(pcap_t *handle, struct pcap_stat *stats) { struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv; ifreq request; int socket = ::socket(AF_INET, SOCK_DGRAM, 0); if (socket < 0) { return -1; } prepare_request(request, handlep->device); if (ioctl(socket, SIOCGIFSTATS, &request, sizeof(struct ifreq)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s", strerror(errno)); close(socket); return -1; } close(socket); handlep->stat.ps_recv += request.ifr_stats.receive.packets; handlep->stat.ps_drop += request.ifr_stats.receive.dropped; *stats = handlep->stat; return 0; }
extern "C" pcap_t * pcap_open_live(const char *device, int snapLength, int /*promisc*/, int /*timeout*/, char *errorBuffer) { // TODO: handle promiscous mode! // we need a socket to talk to the networking stack int socket = ::socket(AF_INET, SOCK_DGRAM, 0); if (socket < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "The networking stack doesn't seem to be available.\n"); return NULL; } struct ifreq request; if (!prepare_request(request, device)) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Interface name \"%s\" is too long.", device); close(socket); return NULL; } // check if the interface exist if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Interface \"%s\" does not exist.\n", device); close(socket); return NULL; } // get link level interface for this interface if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot get link level: %s\n", strerror(errno)); close(socket); return NULL; } close(socket); // no longer needed after this point socket = ::socket(AF_LINK, SOCK_DGRAM, 0); if (socket < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "No link level: %s\n", strerror(errno)); return NULL; } // start monitoring prepare_request(request, request.ifr_parameter.device); if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n", strerror(errno)); close(socket); return NULL; } pcap_t* handle = (pcap_t*)malloc(sizeof(pcap_t)); if (handle == NULL) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "malloc: %s", strerror(errno)); close(socket); return NULL; } memset(handle, 0, sizeof(pcap_t)); handle->bufsize = 65536; // TODO: should be determined by interface MTU // allocate buffer for monitoring the device handle->buffer = (u_char*)malloc(handle->bufsize); if (handle->buffer == NULL) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "buffer malloc: %s", strerror(errno)); free(handle); close(socket); return NULL; } handle->md.device = strdup(device); if (handle->md.device == NULL) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "strdup device: %s", strerror(errno)); free(handle); close(socket); return NULL; } handle->snapshot = snapLength; handle->offset = 0; handle->selectable_fd = socket; handle->fd = socket; handle->linktype = DLT_EN10MB; // TODO: check interface type! handle->read_op = pcap_read_haiku; handle->setfilter_op = pcap_setfilter_haiku; handle->inject_op = pcap_inject_haiku; handle->stats_op = pcap_stats_haiku; // use default hooks where possible handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->close_op = pcap_close_common; return handle; }
extern "C" int pcap_platform_finddevs(pcap_if_t** _allDevices, char* errorBuffer) { // we need a socket to talk to the networking stack int socket = ::socket(AF_INET, SOCK_DGRAM, 0); if (socket < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "The networking stack doesn't seem to be available.\n"); return -1; } // get a list of all interfaces ifconf config; config.ifc_len = sizeof(config.ifc_value); if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) { close(socket); return -1; } uint32 count = (uint32)config.ifc_value; if (count == 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "There are no interfaces defined!\n"); close(socket); return -1; } void* buffer = malloc(count * sizeof(struct ifreq)); if (buffer == NULL) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Out of memory.\n"); close(socket); return -1; } config.ifc_len = count * sizeof(struct ifreq); config.ifc_buf = buffer; if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) { close(socket); return -1; } ifreq* interface = (ifreq*)buffer; for (uint32 i = 0; i < count; i++) { int flags = 0; // get interface type int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0); if (linkSocket < 0) { fprintf(stderr, "No link level: %s\n", strerror(errno)); } else { struct ifreq request; if (!prepare_request(request, interface->ifr_name)) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Interface name \"%s\" is too long.", interface->ifr_name); close(linkSocket); close(socket); return -1; } if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) == 0) { prepare_request(request, request.ifr_parameter.device); if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) { sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr; if (link.sdl_type == IFT_LOOP) flags = IFF_LOOPBACK; } } close(linkSocket); } pcap_add_if(_allDevices, interface->ifr_name, flags, NULL, errorBuffer); interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + interface->ifr_addr.sa_len); } free(buffer); close(socket); return 0; }
void configure_interface(int socket, const char* name, char* const* args, int32 argCount) { ifreq request; if (!prepare_request(request, name)) return; uint32 index = 0; if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0) index = request.ifr_index; bool hasAddress = false, hasMask = false, hasPeer = false; bool hasBroadcast = false, doAutoConfig = false; struct sockaddr address, mask, peer, broadcast; int mtu = -1, metric = -1, media = -1; int addFlags = 0, currentFlags = 0, removeFlags = 0; // try to parse address family int32 familyIndex; int32 i = 0; if (get_address_family(args[i], familyIndex)) i++; if (kFamilies[familyIndex].family != AF_INET) { close(socket); // replace socket with one of the correct address family socket = ::socket(kFamilies[familyIndex].family, SOCK_DGRAM, 0); if (socket < 0) { fprintf(stderr, "%s: Address family \"%s\" is not available.\n", kProgramName, kFamilies[familyIndex].name); exit(1); } } if (index == 0) { // the interface does not exist yet, we have to add it first request.ifr_parameter.base_name[0] = '\0'; request.ifr_parameter.device[0] = '\0'; request.ifr_parameter.sub_type = 0; // the default device is okay for us if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName, strerror(errno)); exit(1); } } // try to parse address if (parse_address(familyIndex, args[i], address)) { hasAddress = true; i++; if (parse_address(familyIndex, args[i], mask)) { hasMask = true; i++; } } // parse parameters and flags while (i < argCount) { if (!strcmp(args[i], "peer")) { if (!parse_address(familyIndex, args[i + 1], peer)) { fprintf(stderr, "%s: Option 'peer' needs valid address " "parameter\n", kProgramName); exit(1); } hasPeer = true; i++; } else if (!strcmp(args[i], "nm") || !strcmp(args[i], "netmask")) { if (hasMask) { fprintf(stderr, "%s: Netmask is specified twice\n", kProgramName); exit(1); } if (!parse_address(familyIndex, args[i + 1], mask)) { fprintf(stderr, "%s: Option 'netmask' needs valid address " "parameter\n", kProgramName); exit(1); } hasMask = true; i++; } else if (!strcmp(args[i], "bc") || !strcmp(args[i], "broadcast")) { if (hasBroadcast) { fprintf(stderr, "%s: broadcast address is specified twice\n", kProgramName); exit(1); } if (!parse_address(familyIndex, args[i + 1], broadcast)) { fprintf(stderr, "%s: Option 'broadcast' needs valid address " "parameter\n", kProgramName); exit(1); } hasBroadcast = true; addFlags |= IFF_BROADCAST; i++; } else if (!strcmp(args[i], "mtu")) { mtu = args[i + 1] ? strtol(args[i + 1], NULL, 0) : 0; if (mtu <= 500) { fprintf(stderr, "%s: Option 'mtu' expected valid max transfer " "unit size\n", kProgramName); exit(1); } i++; } else if (!strcmp(args[i], "metric")) { if (i + 1 >= argCount) { fprintf(stderr, "%s: Option 'metric' exptected parameter\n", kProgramName); exit(1); } metric = strtol(args[i + 1], NULL, 0); i++; } else if (!strcmp(args[i], "media")) { if (ioctl(socket, SIOCGIFMEDIA, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Unable to detect media type\n", kProgramName); exit(1); } if (i + 1 >= argCount) { fprintf(stderr, "%s: Option 'media' exptected parameter\n", kProgramName); exit(1); } if (!media_parse_subtype(args[i + 1], IFM_TYPE(request.ifr_media), &media)) { fprintf(stderr, "%s: Invalid parameter for option 'media': " "'%s'\n", kProgramName, args[i + 1]); exit(1); } i++; } else if (!strcmp(args[i], "up") || !strcmp(args[i], "-down")) { addFlags |= IFF_UP; } else if (!strcmp(args[i], "down") || !strcmp(args[i], "-up")) { removeFlags |= IFF_UP; } else if (!strcmp(args[i], "bcast")) { addFlags |= IFF_BROADCAST; } else if (!strcmp(args[i], "-bcast")) { removeFlags |= IFF_BROADCAST; } else if (!strcmp(args[i], "promisc")) { addFlags |= IFF_PROMISC; } else if (!strcmp(args[i], "-promisc")) { removeFlags |= IFF_PROMISC; } else if (!strcmp(args[i], "allmulti")) { addFlags |= IFF_ALLMULTI; } else if (!strcmp(args[i], "-allmulti")) { removeFlags |= IFF_ALLMULTI; } else if (!strcmp(args[i], "loopback")) { addFlags |= IFF_LOOPBACK; } else if (!strcmp(args[i], "auto-config")) { doAutoConfig = true; } else usage(1); i++; } if ((addFlags & removeFlags) != 0) { fprintf(stderr, "%s: Contradicting flags specified\n", kProgramName); exit(1); } if (doAutoConfig && (hasAddress || hasMask || hasBroadcast || hasPeer)) { fprintf(stderr, "%s: Contradicting changes specified\n", kProgramName); exit(1); } // set address/mask/broadcast/peer if (hasAddress) { memcpy(&request.ifr_addr, &address, address.sa_len); if (ioctl(socket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting address failed: %s\n", kProgramName, strerror(errno)); exit(1); } } if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Getting flags failed: %s\n", kProgramName, strerror(errno)); exit(1); } currentFlags = request.ifr_flags; if (hasMask) { memcpy(&request.ifr_mask, &mask, mask.sa_len); if (ioctl(socket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting subnet mask failed: %s\n", kProgramName, strerror(errno)); exit(1); } } if (hasBroadcast) { memcpy(&request.ifr_broadaddr, &broadcast, broadcast.sa_len); if (ioctl(socket, SIOCSIFBRDADDR, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting broadcast address failed: %s\n", kProgramName, strerror(errno)); exit(1); } } if (hasPeer) { memcpy(&request.ifr_dstaddr, &peer, peer.sa_len); if (ioctl(socket, SIOCSIFDSTADDR, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting peer address failed: %s\n", kProgramName, strerror(errno)); exit(1); } } // set flags if (hasAddress || hasMask || hasBroadcast || hasPeer) removeFlags = IFF_AUTO_CONFIGURED | IFF_CONFIGURING; if (addFlags || removeFlags) { request.ifr_flags = (currentFlags & ~removeFlags) | addFlags; if (ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting flags failed: %s\n", kProgramName, strerror(errno)); } } // set options if (mtu != -1) { request.ifr_mtu = mtu; if (ioctl(socket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting MTU failed: %s\n", kProgramName, strerror(errno)); } } if (metric != -1) { request.ifr_metric = metric; if (ioctl(socket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting metric failed: %s\n", kProgramName, strerror(errno)); } } if (media != -1) { request.ifr_media = media; if (ioctl(socket, SIOCSIFMEDIA, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting media failed: %s\n", kProgramName, strerror(errno)); } } // start auto configuration, if asked for if (doAutoConfig) { BMessage message(kMsgConfigureInterface); message.AddString("device", name); BMessage address; address.AddString("family", "inet"); address.AddBool("auto_config", true); message.AddMessage("address", &address); BMessenger networkServer(kNetServerSignature); if (networkServer.IsValid()) { BMessage reply; status_t status = networkServer.SendMessage(&message, &reply); if (status != B_OK) { fprintf(stderr, "%s: Sending auto-config message failed: %s\n", kProgramName, strerror(status)); } else if (reply.FindInt32("status", &status) == B_OK && status != B_OK) { fprintf(stderr, "%s: Auto-configuring failed: %s\n", kProgramName, strerror(status)); } } else { fprintf(stderr, "%s: The net_server needs to run for the auto " "configuration!\n", kProgramName); } } }
status_t DHCPClient::_Negotiate(dhcp_state state) { int socket = ::socket(AF_INET, SOCK_DGRAM, 0); if (socket < 0) return errno; sockaddr_in local; memset(&local, 0, sizeof(struct sockaddr_in)); local.sin_family = AF_INET; local.sin_len = sizeof(struct sockaddr_in); local.sin_port = htons(DHCP_CLIENT_PORT); local.sin_addr.s_addr = INADDR_ANY; // Enable reusing the port . This is needed in case there is more // than 1 interface that needs to be configured. Note that the only reason // this works is because there is code below to bind to a specific // interface. int option = 1; setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &option, sizeof(option)); if (bind(socket, (struct sockaddr *)&local, sizeof(local)) < 0) { close(socket); return errno; } sockaddr_in broadcast; memset(&broadcast, 0, sizeof(struct sockaddr_in)); broadcast.sin_family = AF_INET; broadcast.sin_len = sizeof(struct sockaddr_in); broadcast.sin_port = htons(DHCP_SERVER_PORT); broadcast.sin_addr.s_addr = INADDR_BROADCAST; option = 1; setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option)); if (state == INIT) { // The local interface does not have an address yet, bind the socket // to the device directly. int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0); if (linkSocket >= 0) { // we need to know the index of the device to be able to bind to it ifreq request; prepare_request(request, Device()); if (ioctl(linkSocket, SIOCGIFINDEX, &request, sizeof(struct ifreq)) == 0) { setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, &request.ifr_index, sizeof(int)); } close(linkSocket); } } bigtime_t previousLeaseTime = fLeaseTime; fLeaseTime = 0; fRenewalTime = 0; fRebindingTime = 0; status_t status = B_ERROR; time_t timeout; uint32 tries; _ResetTimeout(socket, timeout, tries); dhcp_message discover(DHCP_DISCOVER); _PrepareMessage(discover, state); dhcp_message request(DHCP_REQUEST); _PrepareMessage(request, state); // send discover/request message _SendMessage(socket, state == INIT ? discover : request, state != RENEWAL ? broadcast : fServer); // no need to check the status; in case of an error we'll just send // the message again // receive loop until we've got an offer and acknowledged it while (state != ACKNOWLEDGED) { char buffer[2048]; ssize_t bytesReceived = recvfrom(socket, buffer, sizeof(buffer), 0, NULL, NULL); if (bytesReceived < 0 && errno == B_TIMED_OUT) { // depending on the state, we'll just try again if (!_TimeoutShift(socket, timeout, tries)) { close(socket); return B_TIMED_OUT; } if (state == INIT) _SendMessage(socket, discover, broadcast); else { _SendMessage(socket, request, state != RENEWAL ? broadcast : fServer); } continue; } else if (bytesReceived < 0) break; dhcp_message *message = (dhcp_message *)buffer; if (message->transaction_id != htonl(fTransactionID) || !message->HasOptions() || memcmp(message->mac_address, discover.mac_address, discover.hardware_address_length)) { // this message is not for us continue; } switch (message->Type()) { case DHCP_NONE: default: // ignore this message break; case DHCP_OFFER: { // first offer wins if (state != INIT) break; // collect interface options fAssignedAddress = message->your_address; fConfiguration.MakeEmpty(); fConfiguration.AddString("device", Device()); fConfiguration.AddBool("auto", true); BMessage address; address.AddString("family", "inet"); address.AddString("address", _ToString(fAssignedAddress)); _ParseOptions(*message, address); fConfiguration.AddMessage("address", &address); // request configuration from the server _ResetTimeout(socket, timeout, tries); state = REQUESTING; _PrepareMessage(request, state); status = _SendMessage(socket, request, broadcast); // we're sending a broadcast so that all potential offers // get an answer break; } case DHCP_ACK: { if (state != REQUESTING && state != REBINDING && state != RENEWAL) continue; // TODO: we might want to configure the stuff, don't we? BMessage address; _ParseOptions(*message, address); // TODO: currently, only lease time and DNS is updated this way // our address request has been acknowledged state = ACKNOWLEDGED; // configure interface BMessage reply; status = Target().SendMessage(&fConfiguration, &reply); if (status == B_OK) status = reply.FindInt32("status", &fStatus); break; } case DHCP_NACK: if (state != REQUESTING) continue; // try again (maybe we should prefer other servers if this // happens more than once) status = _SendMessage(socket, discover, broadcast); if (status == B_OK) state = INIT; break; } } close(socket); if (status == B_OK && fLeaseTime > 0) { // notify early enough when the lease is if (fRenewalTime == 0) fRenewalTime = fLeaseTime * 2/3; if (fRebindingTime == 0) fRebindingTime = fLeaseTime * 5/6; bigtime_t now = system_time(); _RestartLease(fRenewalTime); fLeaseTime += now; fRenewalTime += now; fRebindingTime += now; // make lease times absolute } else { fLeaseTime = previousLeaseTime; bigtime_t now = system_time(); fRenewalTime = (fLeaseTime - now) * 2/3 + now; fRebindingTime = (fLeaseTime - now) * 5/6 + now; } return status; }
int retrieve_stock_price(struct stock_price* price_info, char* url, parse_body_string_fun parse_body_string) { int nret = 0; struct request * request = NULL; char *host_name = NULL; char *full_path = NULL; char *request_string = NULL; char *response_string = NULL; char *body_string = NULL; int body_size; char *p = NULL; struct ghbnwt_context *ctx = NULL; struct sockaddr_in sa; int res; int bufsize; int sock; url_parse (url, &host_name, &full_path); request = prepare_request(host_name, full_path); nret = 1; // Get server's ip adress. ctx =(struct ghbnwt_context *) malloc(sizeof(struct ghbnwt_context)); ctx->host_name = host_name; ctx->hptr = gethostbyname (ctx->host_name); if (!ctx->hptr) { nret = -1; goto exit; } // Get socket descriptor. sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); // Connect to server. memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons (80); memcpy (&sa.sin_addr, *ctx->hptr->h_addr_list, 4); if(-1 == connect (sock, (const struct sockaddr *)&sa, sizeof(sa))) { nret = -1; goto exit; } // Send request. p = request_string = organize_request_string(request); bufsize = strlen(request_string); res = 0; while (bufsize > 0) { res = send(sock, p, bufsize, 0); if (res <= 0) break; p += res; bufsize -= res; } // Receive response. response_string = receive_response(sock, &body_string, &body_size); if (response_string == NULL) { nret = -1; } else if (parse_response(response_string) == 200) { body_string = read_body(sock, body_string, body_size); if (body_string) { // Parse string of body if (body_string) parse_body_string(price_info, body_string); } } else { nret = -1; } exit: // Close a connection. close(sock); // Reclaim heap memory space. free(host_name); free(full_path); free(request->headers); free(request); free(request_string); free(response_string); free(body_string); return nret; }
void list_interface(int socket, const char* name) { ifreq request; if (!prepare_request(request, name)) return; if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Interface \"%s\" does not exist.\n", kProgramName, name); return; } printf("%s", name); size_t length = strlen(name); if (length < 8) putchar('\t'); else printf("\n\t"); // get link level interface for this interface int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0); if (linkSocket < 0) { printf("No link level: %s\n", strerror(errno)); } else { const char *type = "unknown"; char address[256]; strcpy(address, "none"); if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) == 0) { prepare_request(request, request.ifr_parameter.device); if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) { sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr; switch (link.sdl_type) { case IFT_ETHER: { type = "Ethernet"; if (link.sdl_alen > 0) { uint8 *mac = (uint8 *)LLADDR(&link); sprintf(address, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } else strcpy(address, "not available"); break; } case IFT_LOOP: type = "Local Loopback"; break; case IFT_MODEM: type = "Modem"; break; } } } printf("Hardware Type: %s, Address: %s\n", type, address); close(linkSocket); } if (ioctl(socket, SIOCGIFMEDIA, &request, sizeof(struct ifreq)) == 0 && (request.ifr_media & IFM_ACTIVE) != 0) { // dump media state in case we're linked const char* type = "unknown"; bool show = false; for (int32 i = 0; kMediaTypes[i].type >= 0; i++) { // loopback don't really have a media anyway if (IFM_TYPE(request.ifr_media) == 0/*IFT_LOOP*/) break; // only check for generic or correct subtypes if (kMediaTypes[i].type && kMediaTypes[i].type != IFM_TYPE(request.ifr_media)) continue; for (int32 j = 0; kMediaTypes[i].subtypes[j].subtype >= 0; j++) { if (kMediaTypes[i].subtypes[j].subtype == IFM_SUBTYPE(request.ifr_media)) { // found a match type = kMediaTypes[i].subtypes[j].pretty; show = true; break; } } } if (show) printf("\tMedia Type: %s\n", type); } uint32 flags = 0; if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0) flags = request.ifr_flags; for (int32 i = 0; kFamilies[i].family >= 0; i++) { int familySocket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0); if (familySocket < 0) continue; if (ioctl(familySocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) { printf("\t%s addr: ", kFamilies[i].name); kFamilies[i].print_address(&request.ifr_addr); if ((flags & IFF_BROADCAST) != 0 && ioctl(familySocket, SIOCGIFBRDADDR, &request, sizeof(struct ifreq)) == 0 && request.ifr_broadaddr.sa_family == kFamilies[i].family) { printf(", Bcast: "); kFamilies[i].print_address(&request.ifr_broadaddr); } if (ioctl(familySocket, SIOCGIFNETMASK, &request, sizeof(struct ifreq)) == 0 && request.ifr_mask.sa_family == kFamilies[i].family) { printf(", Mask: "); kFamilies[i].print_address(&request.ifr_mask); } putchar('\n'); } close(familySocket); } // Print MTU, metric, flags printf("\tMTU: "); if (ioctl(socket, SIOCGIFMTU, &request, sizeof(struct ifreq)) == 0) printf("%d", request.ifr_mtu); else printf("-"); printf(", Metric: "); if (ioctl(socket, SIOCGIFMETRIC, &request, sizeof(struct ifreq)) == 0) printf("%d", request.ifr_metric); else printf("-"); if (flags != 0) { const struct { int value; const char *name; } kFlags[] = { {IFF_UP, "up"}, {IFF_NOARP, "noarp"}, {IFF_BROADCAST, "broadcast"}, {IFF_LOOPBACK, "loopback"}, {IFF_PROMISC, "promiscuous"}, {IFF_ALLMULTI, "allmulti"}, {IFF_AUTOUP, "autoup"}, {IFF_LINK, "link"}, {IFF_AUTO_CONFIGURED, "auto-configured"}, {IFF_CONFIGURING, "configuring"}, }; bool first = true; for (uint32 i = 0; i < sizeof(kFlags) / sizeof(kFlags[0]); i++) { if ((flags & kFlags[i].value) != 0) { if (first) { printf(","); first = false; } putchar(' '); printf(kFlags[i].name); } } } putchar('\n'); // Print statistics if (ioctl(socket, SIOCGIFSTATS, &request, sizeof(struct ifreq)) == 0) { printf("\tReceive: %d packets, %d errors, %Ld bytes, %d mcasts, %d dropped\n", request.ifr_stats.receive.packets, request.ifr_stats.receive.errors, request.ifr_stats.receive.bytes, request.ifr_stats.receive.multicast_packets, request.ifr_stats.receive.dropped); printf("\tTransmit: %d packets, %d errors, %Ld bytes, %d mcasts, %d dropped\n", request.ifr_stats.send.packets, request.ifr_stats.send.errors, request.ifr_stats.send.bytes, request.ifr_stats.send.multicast_packets, request.ifr_stats.send.dropped); printf("\tCollisions: %d\n", request.ifr_stats.collisions); } putchar('\n'); }
int main(int argc, char **argv) { int run_time = 30; int op = O_RDONLY; int qd = 4; int end_of_device = 0; int opt, i, j, max_req, rc, ios_ready, in_flight, count; unsigned long arena_size; unsigned long seed = time(NULL); unsigned long mix_seed = time(NULL); unsigned long random_range = 0; unsigned char *arena; struct iocb *iocbs; struct iocb *ioptr; struct iocb **iolist; struct iocb **iolist_ptr; struct io_event *events; struct timespec start, end, now; unsigned long total_data, total_writes, total_count; int min_data, max_data; io_context_t ioctx; double mbs, actual_time; struct option options[] = { { "help", no_argument, NULL, 'h' }, { "write", optional_argument, NULL, 'w' }, { "loop", no_argument, NULL, 'l' }, { "mixseed", required_argument, NULL, 'm' }, { "qd", required_argument, NULL, 'q' }, { "random", optional_argument, NULL, 'r' }, { "range", required_argument, NULL, 'a' }, { "size", required_argument, NULL, 's' }, { "time", required_argument, NULL, 't' }, { NULL } }; req_size = 1024 * 1024; write_pct = 0.0; for (;;) { opt = getopt_long(argc, argv, "hwlq:s:t:", options, NULL); if (opt == -1) break; switch (opt) { case 'w': op = O_RDWR; write_pct = 1.0; if (optarg) write_pct = strtod(optarg, NULL) / 100.0; if (write_pct < 1.0) random_offsets = 1; break; case 'l': loop_at_end = 1; break; case 'm': mix_seed = strtoul(optarg, NULL, 0); break; case 'q': qd = atoi(optarg); break; case 't': run_time = atoi(optarg); break; case 's': req_size = strtoul(optarg, NULL, 0); break; case 'r': random_offsets = 1; if (optarg) seed = strtoul(optarg, NULL, 0); else seed = time(NULL); break; case 'a': random_range = strtoul(optarg, NULL, 0); break; case 'h': case '?': default: usage(argv[0]); break; } } if (run_time < 1) { fprintf(stderr, "%s: run time must be at least 1 second\n", argv[0]); exit(1); } if (qd < 0 || qd > 64) { fprintf(stderr, "%s: queue depth must be between 1 and 64\n", argv[0]); exit(1); } if (req_size < 4096 || req_size > (16 * 1024 * 1024)) { fprintf(stderr, "%s: request size must be between 4K and 16M\n", argv[0]); exit(1); } /* Always do a multiple of a page for direct IO. */ req_size &= ~4095; if (random_range) { random_range /= req_size; if (random_range < 2) { fprintf(stderr, "%s: random range gives no " "randomness\n", argv[0]); exit(1); } } if (optind == argc) { fprintf(stderr, "%s: need devices to benchmark\n", argv[0]); exit(1); } ndev = argc - optind; devs = malloc(ndev * sizeof(*devs)); if (!ndev) { fprintf(stderr, "%s: no memory for devices\n", argv[0]); exit(1); } for (i = 0; i < ndev; i++) { devs[i].replace = -1; devs[i].io_base = NULL; devs[i].offset = 0; devs[i].count = 0; devs[i].writes = 0; devs[i].status = ' '; devs[i].name = argv[optind++]; devs[i].fd = open(devs[i].name, op|O_DIRECT|O_SYNC); if (devs[i].fd < 0) { fprintf(stderr, "%s: opening ", argv[0]); perror(devs[i].name); exit(1); } devs[i].size = lseek(devs[i].fd, 0, SEEK_END); if (devs[i].size < 0) { fprintf(stderr, "%s: lseek ", argv[0]); perror(devs[i].name); exit(1); } if (random_offsets) { unsigned long t = seed + i; devs[i].random_range = devs[i].size / req_size; if (random_range && devs[i].random_range > random_range) devs[i].random_range = random_range; devs[i].off_rand_state[2] = t >> 16; devs[i].off_rand_state[1] = t & 0xffff; devs[i].off_rand_state[0] = 0x330e; t = mix_seed + i; devs[i].rw_rand_state[2] = t >> 16; devs[i].rw_rand_state[1] = t & 0xffff; devs[i].rw_rand_state[0] = 0x330e; } } /* The arena needs to be big enough to host the maximum number of * requests possible, plus an extra set of requests to pass around * the devices to fairly share any memory fragmentation seen. */ max_req = ndev * qd; arena_size = (max_req + qd) * req_size; arena = mmap(NULL, arena_size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_POPULATE|MAP_PRIVATE, -1, 0); if (arena == MAP_FAILED) { fprintf(stderr, "%s: unable to allocate arena\n", argv[0]); exit(1); } memset(arena, 0, arena_size); iocbs = malloc(max_req * sizeof(*iocbs)); if (!iocbs) { fprintf(stderr, "%s: no memory for IOCBs\n", argv[0]); exit(1); } iolist = malloc(max_req * sizeof(*iocbs)); if (!iolist) { fprintf(stderr, "%s: no memory for IOCB list\n", argv[0]); exit(1); } events = malloc(max_req * sizeof(*events)); if (!iolist) { fprintf(stderr, "%s: no memory for IOCB list\n", argv[0]); exit(1); } rc = io_queue_init(max_req, &ioctx); if (rc < 0) { fprintf(stderr, "%s: unable to initialize IO context: %s\n", argv[0], strerror(-rc)); exit(1); } /* Prepopulate our IO requests */ ios_ready = 0; ioptr = iocbs; iolist_ptr = iolist; for (i = 0; i < qd; i++) { for (j = 0; j < ndev; j++) { if (!devs[j].io_base) devs[j].io_base = ioptr; /* Initial iocb prep, will be overwritten in * prepare_request() with proper offset and operation. */ io_prep_pwrite(ioptr, devs[j].fd, arena, req_size, 0); ioptr->data = &devs[j]; arena += req_size; if (prepare_request(&devs[j], ioptr)) { fprintf(stderr, "Premature end of device for " "%s\n", devs[j].name); exit(1); } *iolist_ptr++ = ioptr++; ios_ready++; } } /* Populate the replacement list */ buf_dev = 0; buf_next = NULL; buf_ready = NULL; for (i = 0; i < qd; i++) { buf_p = (struct buf_list *) arena; buf_p->next = buf_ready; buf_ready = buf_p; arena += req_size; } clock_gettime(CLOCK_MONOTONIC_HR, &now); end.tv_sec = now.tv_sec + run_time; end.tv_nsec = now.tv_nsec; devs[0].replace = 0; in_flight = 0; clock_gettime(CLOCK_MONOTONIC_HR, &start); /* Prime the IO pump with our prepared requests */ rc = io_submit(ioctx, ios_ready, iolist); if (rc < 0) { fprintf(stderr, "%s: io_submit() failed: %s\n", argv[0], strerror(-rc)); exit(1); } in_flight += ios_ready; iolist_ptr = iolist; ios_ready = 0; /* Main IO loop */ while (time_before(&now, &end) && !end_of_device) { count = io_getevents(ioctx, 1, in_flight, events, NULL); if (count <= 0) { fprintf(stderr, "%s: io_getevents() failed: " "%s\n", argv[0], strerror(-rc)); exit(1); } for (i = 0; i < count && !end_of_device; i++) { struct iocb *iocb = events[i].obj; struct dev_info *dev = iocb->data; if (events[i].res2) { fprintf(stderr, "%s: got error for %s:" " %lu\n", argv[0], dev->name, events[i].res2); exit(1); } end_of_device = prepare_request(dev, iocb); if (!end_of_device) { *iolist_ptr++ = iocb; ios_ready++; } in_flight--; } /* If we're here, then odds are good we have IO to submit. * Check just in case something woke us up other than an * IO completion. */ if (ios_ready) { rc = io_submit(ioctx, ios_ready, iolist); if (rc < 0) { fprintf(stderr, "%s: io_submit() failed: %s\n", argv[0], strerror(-rc)); exit(1); } in_flight += ios_ready; iolist_ptr = iolist; ios_ready = 0; } clock_gettime(CLOCK_MONOTONIC_HR, &now); } if (end_of_device) { actual_time = now.tv_nsec - start.tv_nsec; actual_time /= 10e9; actual_time += now.tv_sec - start.tv_sec; } else actual_time = run_time; /* Ok, test time is finished, drain outstanding requests */ while (in_flight) { count = io_getevents(ioctx, 1, in_flight, events, NULL); if (count <= 0) { fprintf(stderr, "%s: draining io_getevents() failed: " "%s\n", argv[0], strerror(-rc)); exit(1); } for (i = 0; i < count; i++) { struct iocb *iocb = events[i].obj; struct dev_info *dev = iocb->data; if (events[i].res2) { fprintf(stderr, "%s: draining got error for %s:" " %lu\n", argv[0], dev->name, events[i].res2); exit(1); } in_flight--; } } /* Find the targets that wrote the min and max data so we can * calculate the skew. */ min_data = max_data = 0; total_data = total_writes = total_count= 0; for (i = 0; i < ndev; i++) { if (devs[i].count < devs[min_data].count) min_data = i; if (devs[i].count > devs[max_data].count) max_data = i; total_data += devs[i].count * req_size; total_writes += devs[i].writes; total_count += devs[i].count; } devs[min_data].status = 'm'; devs[max_data].status = 'M'; printf("run time: %.6f seconds%s\n", actual_time, end_of_device ? " (end of device reached)" : ""); printf("queue depth: %d\n", qd); printf("operation: %s ", random_offsets ? "random" : "sequential"); if (write_pct >= 1.0) printf("write\n"); else if (write_pct == 0.0) printf("read\n"); else { printf("mixed (goal %.02f%% writes)\n", write_pct * 100); printf("random request seed: %lu\n", mix_seed); } if (random_offsets) printf("random offset seed: %lu\n", seed); if (random_range) printf("random range: %lu bytes\n", random_range * req_size); printf("request size: %lu bytes\n\n", req_size); for (i = 0; i < ndev; i++) { mbs = ((double) devs[i].count * req_size) / actual_time; mbs /= 1024 * 1024; printf("%c %s: %lu %.2f MB/s", devs[i].status, devs[i].name, devs[i].count * req_size, mbs); if (write_pct != 0.0 && write_pct < 1.0) { printf(" %02.f%% writes", 100.0 * devs[i].writes / devs[i].count); } printf("\n"); } mbs = (double) total_data / actual_time; mbs /= 1024 * 1024; printf("total: %lu %.2f MB/s", total_data, mbs); mbs = (double) (devs[max_data].count - devs[min_data].count); mbs *= req_size; mbs /= actual_time; mbs /= 1024 * 1024; printf(" skew %.2f MB/s", mbs); if (write_pct != 0.0 && write_pct < 1.0) printf(" %02.f%% writes", 100.0 * total_writes / total_count); printf("\n"); return 0; }
status_t NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage) { const char *device; if (interface.FindString("device", &device) != B_OK) return B_BAD_VALUE; ifreq request; if (!prepare_request(request, device)) return B_ERROR; bool startAutoConfig = false; int32 flags; if (interface.FindInt32("flags", &flags) < B_OK) flags = IFF_UP; bool autoConfigured; if (interface.FindBool("auto", &autoConfigured) == B_OK && autoConfigured) flags |= IFF_AUTO_CONFIGURED; int32 mtu; if (interface.FindInt32("mtu", &mtu) < B_OK) mtu = -1; int32 metric; if (interface.FindInt32("metric", &metric) < B_OK) metric = -1; BMessage addressMessage; for (int32 index = 0; interface.FindMessage("address", index, &addressMessage) == B_OK; index++) { const char* family; if (addressMessage.FindString("family", &family) < B_OK) continue; int32 familyIndex; if (!get_family_index(family, familyIndex)) { // we don't support this family continue; } int familySocket = socket; if (family_at_index(familyIndex) != AF_INET) socket = ::socket(family_at_index(familyIndex), SOCK_DGRAM, 0); if (socket < 0) { // the family is not available in this environment continue; } uint32 interfaceIndex = 0; if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0) interfaceIndex = request.ifr_index; if (interfaceIndex == 0) { // we need to create the interface first request.ifr_parameter.base_name[0] = '\0'; request.ifr_parameter.device[0] = '\0'; request.ifr_parameter.sub_type = 0; // the default device is okay for us if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not add interface: %s\n", Name(), strerror(errno)); return errno; } } // retrieve addresses bool autoConfig; if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK) autoConfig = false; #if 0 if (autoConfig && fromMessage) { // we don't accept auto-config messages this way continue; } #endif bool hasAddress = false, hasMask = false, hasPeer = false; bool hasBroadcast = false; struct sockaddr address, mask, peer, broadcast, gateway; const char* string; if (!autoConfig) { if (addressMessage.FindString("address", &string) == B_OK && parse_address(familyIndex, string, address)) { hasAddress = true; if (addressMessage.FindString("mask", &string) == B_OK && parse_address(familyIndex, string, mask)) hasMask = true; } if (addressMessage.FindString("peer", &string) == B_OK && parse_address(familyIndex, string, peer)) hasPeer = true; if (addressMessage.FindString("broadcast", &string) == B_OK && parse_address(familyIndex, string, broadcast)) hasBroadcast = true; } route_entry route; memset(&route, 0, sizeof(route_entry)); route.flags = RTF_STATIC | RTF_DEFAULT; request.ifr_route = route; if (autoConfig) { _QuitLooperForDevice(device); startAutoConfig = true; } else if (addressMessage.FindString("gateway", &string) == B_OK && parse_address(familyIndex, string, gateway)) { // add gateway route, if we're asked for it ioctl(socket, SIOCDELRT, &request, sizeof(request)); // Try to remove a previous default route, doesn't matter // if it fails. route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY; route.gateway = &gateway; request.ifr_route = route; if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not add route for %s: %s\n", Name(), device, strerror(errno)); } } // set addresses if (hasAddress) { memcpy(&request.ifr_addr, &address, address.sa_len); if (ioctl(familySocket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting address failed: %s\n", Name(), strerror(errno)); continue; } } if (ioctl(familySocket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Getting flags failed: %s\n", Name(), strerror(errno)); continue; } int32 currentFlags = request.ifr_flags; if (hasMask) { memcpy(&request.ifr_mask, &mask, mask.sa_len); if (ioctl(familySocket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting subnet mask failed: %s\n", Name(), strerror(errno)); continue; } } if (hasBroadcast) { memcpy(&request.ifr_broadaddr, &broadcast, broadcast.sa_len); if (ioctl(familySocket, SIOCSIFBRDADDR, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting broadcast address failed: %s\n", Name(), strerror(errno)); continue; } } if (hasPeer) { memcpy(&request.ifr_dstaddr, &peer, peer.sa_len); if (ioctl(familySocket, SIOCSIFDSTADDR, &request, sizeof(struct ifreq)) < 0) { fprintf(stderr, "%s: Setting peer address failed: %s\n", Name(), strerror(errno)); continue; } } // set flags if (flags != 0) { request.ifr_flags = (currentFlags & ~IFF_CONFIGURING) | flags; if (!autoConfigured) request.ifr_flags = request.ifr_flags & ~IFF_AUTO_CONFIGURED; if (ioctl(familySocket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno)); } // set options if (mtu != -1) { request.ifr_mtu = mtu; if (ioctl(familySocket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0) fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), strerror(errno)); } if (metric != -1) { request.ifr_metric = metric; if (ioctl(familySocket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0) fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), strerror(errno)); } } if (startAutoConfig) { // start auto configuration AutoconfigLooper* looper = new AutoconfigLooper(this, device); looper->Run(); fDeviceMap[device] = looper; } return B_OK; }
extern "C" pcap_t * pcap_create_interface(const char *device, char *errorBuffer) { // TODO: handle promiscous mode! // we need a socket to talk to the networking stack int socket = ::socket(AF_INET, SOCK_DGRAM, 0); if (socket < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "The networking stack doesn't seem to be available.\n"); return NULL; } struct ifreq request; if (!prepare_request(request, device)) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Interface name \"%s\" is too long.", device); close(socket); return NULL; } // check if the interface exist if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Interface \"%s\" does not exist.\n", device); close(socket); return NULL; } close(socket); // no longer needed after this point // get link level interface for this interface socket = ::socket(AF_LINK, SOCK_DGRAM, 0); if (socket < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "No link level: %s\n", strerror(errno)); return NULL; } // start monitoring if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n", strerror(errno)); close(socket); return NULL; } pcap_t* handle = pcap_create_common(errorBuffer, sizeof (struct pcap_haiku)); if (handle == NULL) { snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "malloc: %s", strerror(errno)); close(socket); return NULL; } handle->selectable_fd = socket; handle->fd = socket; handle->activate_op = pcap_activate_haiku; return handle; }