diff --git a/headers/posix/net/if.h b/headers/posix/net/if.h index 7b6380340a..868657a3a4 100644 --- a/headers/posix/net/if.h +++ b/headers/posix/net/if.h @@ -64,6 +64,18 @@ struct ifaliasreq { uint32_t ifra_flags; }; +/* used with SIOCGIFMEDIA */ +struct ifmediareq { + char ifm_name[IF_NAMESIZE]; + int ifm_current; + int ifm_mask; + int ifm_status; + int ifm_active; + int ifm_count; + int* ifm_ulist; +}; + + /* interface flags */ #define IFF_UP 0x0001 #define IFF_BROADCAST 0x0002 /* valid broadcast address */ diff --git a/src/add-ons/kernel/network/stack/datalink.cpp b/src/add-ons/kernel/network/stack/datalink.cpp index 2f0ed7c197..c98efc9fbf 100644 --- a/src/add-ons/kernel/network/stack/datalink.cpp +++ b/src/add-ons/kernel/network/stack/datalink.cpp @@ -901,20 +901,39 @@ interface_protocol_control(net_datalink_protocol* _protocol, int32 option, { // set media struct ifreq request; - if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK) + if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK) return B_BAD_ADDRESS; - return interface->DeviceInterface()->device->module->set_media( - interface->device, request.ifr_media); + status_t status + = interface->device->module->set_media( + interface->device, request.ifr_media); + if (status == B_NOT_SUPPORTED) { + // TODO: this isn't so nice, and should be solved differently + // (for example by removing the set_media() call altogether, or + // making it able to deal properly with FreeBSD drivers as well) + // try driver directly + status = interface->device->module->control( + interface->device, SIOCSIFMEDIA, &request, sizeof(request)); + } + + return status; } case SIOCGIFMEDIA: { // get media - struct ifreq request; - request.ifr_media = interface->device->media; + struct ifmediareq request; + if (user_memcpy(&request, argument, IF_NAMESIZE) != B_OK) + return B_BAD_ADDRESS; - return user_memcpy(&((struct ifreq*)argument)->ifr_media, - &request.ifr_media, sizeof(request.ifr_media)); + // TODO: see above. + if (interface->device->module->control(interface->device, + SIOCGIFMEDIA, &request, + sizeof(struct ifmediareq)) != B_OK) { + memset(&request, 0, sizeof(struct ifmediareq)); + request.ifm_current = interface->device->media; + } + + return user_memcpy(argument, &request, sizeof(struct ifmediareq)); } case SIOCGIFMETRIC: diff --git a/src/kits/network/libnetapi/Jamfile b/src/kits/network/libnetapi/Jamfile index 33a5544a4e..aa7280bc79 100644 --- a/src/kits/network/libnetapi/Jamfile +++ b/src/kits/network/libnetapi/Jamfile @@ -2,11 +2,15 @@ SubDir HAIKU_TOP src kits network libnetapi ; UsePrivateHeaders net shared ; +UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] + : true ; +UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_wlan ] : true ; + SharedLibrary libbnetapi.so : init.cpp DynamicBuffer.cpp NetEndpoint.cpp - NetAddress.cpp + NetAddress.cpp NetBuffer.cpp NetDebug.cpp @@ -14,6 +18,7 @@ SharedLibrary libbnetapi.so : NetworkAddressResolver.cpp NetworkCookie.cpp NetworkCookieJar.cpp + NetworkDevice.cpp NetworkInterface.cpp NetworkRoster.cpp diff --git a/src/kits/network/libnetapi/NetworkInterface.cpp b/src/kits/network/libnetapi/NetworkInterface.cpp index 223dc24078..fce99cdd25 100644 --- a/src/kits/network/libnetapi/NetworkInterface.cpp +++ b/src/kits/network/libnetapi/NetworkInterface.cpp @@ -76,8 +76,8 @@ do_ifaliasreq(const char* name, int32 option, } -static status_t -do_request(int family, ifreq& request, const char* name, int option) +template status_t +do_request(int family, T& request, const char* name, int option) { int socket = ::socket(family, SOCK_DGRAM, 0); if (socket < 0) @@ -85,9 +85,9 @@ do_request(int family, ifreq& request, const char* name, int option) FileDescriptorCloser closer(socket); - strlcpy(request.ifr_name, name, IF_NAMESIZE); + strlcpy(((struct ifreq&)request).ifr_name, name, IF_NAMESIZE); - if (ioctl(socket, option, &request, sizeof(struct ifreq)) < 0) + if (ioctl(socket, option, &request, sizeof(T)) < 0) return errno; return B_OK; @@ -248,11 +248,14 @@ BNetworkInterface::MTU() const int32 BNetworkInterface::Media() const { - ifreq request; + ifmediareq request; + request.ifm_count = 0; + request.ifm_ulist = NULL; + if (do_request(AF_INET, request, Name(), SIOCGIFMEDIA) != B_OK) return -1; - return request.ifr_media; + return request.ifm_current; } diff --git a/src/libs/compat/freebsd_network/compat/net/if.h b/src/libs/compat/freebsd_network/compat/net/if.h index 1cb6a9f1f1..f162a24f5a 100644 --- a/src/libs/compat/freebsd_network/compat/net/if.h +++ b/src/libs/compat/freebsd_network/compat/net/if.h @@ -56,16 +56,6 @@ #define IFQ_MAXLEN 50 -struct ifmediareq { - char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - int ifm_current; /* current media options */ - int ifm_mask; /* don't care mask */ - int ifm_status; /* media status */ - int ifm_active; /* active options */ - int ifm_count; /* # entries in ifm_ulist array */ - int* ifm_ulist; /* media words */ -}; - /* * Structure describing information about an interface * which may be of interest to management entities.