LCOV - code coverage report
Current view: top level - src/drivers - linux_ioctl.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 86 117 73.5 %
Date: 2016-10-02 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Linux ioctl helper functions for driver wrappers
       3             :  * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : #include <sys/ioctl.h>
      11             : #include <net/if.h>
      12             : #include <net/if_arp.h>
      13             : 
      14             : #include "utils/common.h"
      15             : #include "linux_ioctl.h"
      16             : 
      17             : 
      18        6149 : int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
      19             : {
      20             :         struct ifreq ifr;
      21             :         int ret;
      22             : 
      23        6149 :         if (sock < 0)
      24           0 :                 return -1;
      25             : 
      26        6149 :         os_memset(&ifr, 0, sizeof(ifr));
      27        6149 :         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
      28             : 
      29        6149 :         if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
      30          94 :                 ret = errno ? -errno : -999;
      31          94 :                 wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
      32          94 :                            ifname, strerror(errno));
      33          94 :                 return ret;
      34             :         }
      35             : 
      36        6055 :         if (dev_up) {
      37        3056 :                 if (ifr.ifr_flags & IFF_UP)
      38           2 :                         return 0;
      39        3054 :                 ifr.ifr_flags |= IFF_UP;
      40             :         } else {
      41        2999 :                 if (!(ifr.ifr_flags & IFF_UP))
      42          55 :                         return 0;
      43        2944 :                 ifr.ifr_flags &= ~IFF_UP;
      44             :         }
      45             : 
      46        5998 :         if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
      47           0 :                 ret = errno ? -errno : -999;
      48           0 :                 wpa_printf(MSG_ERROR, "Could not set interface %s flags (%s): "
      49             :                            "%s",
      50           0 :                            ifname, dev_up ? "UP" : "DOWN", strerror(errno));
      51           0 :                 return ret;
      52             :         }
      53             : 
      54        5998 :         return 0;
      55             : }
      56             : 
      57             : 
      58        3615 : int linux_iface_up(int sock, const char *ifname)
      59             : {
      60             :         struct ifreq ifr;
      61             :         int ret;
      62             : 
      63        3615 :         if (sock < 0)
      64           0 :                 return -1;
      65             : 
      66        3615 :         os_memset(&ifr, 0, sizeof(ifr));
      67        3615 :         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
      68             : 
      69        3615 :         if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
      70           3 :                 ret = errno ? -errno : -999;
      71           3 :                 wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
      72           3 :                            ifname, strerror(errno));
      73           3 :                 return ret;
      74             :         }
      75             : 
      76        3612 :         return !!(ifr.ifr_flags & IFF_UP);
      77             : }
      78             : 
      79             : 
      80        5085 : int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr)
      81             : {
      82             :         struct ifreq ifr;
      83             : 
      84        5085 :         os_memset(&ifr, 0, sizeof(ifr));
      85        5085 :         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
      86        5085 :         if (ioctl(sock, SIOCGIFHWADDR, &ifr)) {
      87           0 :                 wpa_printf(MSG_ERROR, "Could not get interface %s hwaddr: %s",
      88           0 :                            ifname, strerror(errno));
      89           0 :                 return -1;
      90             :         }
      91             : 
      92        5085 :         if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
      93           0 :                 wpa_printf(MSG_ERROR, "%s: Invalid HW-addr family 0x%04x",
      94           0 :                            ifname, ifr.ifr_hwaddr.sa_family);
      95           0 :                 return -1;
      96             :         }
      97        5085 :         os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
      98             : 
      99        5085 :         return 0;
     100             : }
     101             : 
     102             : 
     103         251 : int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr)
     104             : {
     105             :         struct ifreq ifr;
     106             : 
     107         251 :         os_memset(&ifr, 0, sizeof(ifr));
     108         251 :         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
     109         251 :         os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
     110         251 :         ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
     111             : 
     112         251 :         if (ioctl(sock, SIOCSIFHWADDR, &ifr)) {
     113           0 :                 wpa_printf(MSG_DEBUG, "Could not set interface %s hwaddr: %s",
     114           0 :                            ifname, strerror(errno));
     115           0 :                 return -1;
     116             :         }
     117             : 
     118         251 :         return 0;
     119             : }
     120             : 
     121             : 
     122             : #ifndef SIOCBRADDBR
     123             : #define SIOCBRADDBR 0x89a0
     124             : #endif
     125             : #ifndef SIOCBRDELBR
     126             : #define SIOCBRDELBR 0x89a1
     127             : #endif
     128             : #ifndef SIOCBRADDIF
     129             : #define SIOCBRADDIF 0x89a2
     130             : #endif
     131             : #ifndef SIOCBRDELIF
     132             : #define SIOCBRDELIF 0x89a3
     133             : #endif
     134             : 
     135             : 
     136          22 : int linux_br_add(int sock, const char *brname)
     137             : {
     138          22 :         if (ioctl(sock, SIOCBRADDBR, brname) < 0) {
     139           0 :                 wpa_printf(MSG_DEBUG, "Could not add bridge %s: %s",
     140           0 :                            brname, strerror(errno));
     141           0 :                 return -1;
     142             :         }
     143             : 
     144          22 :         return 0;
     145             : }
     146             : 
     147             : 
     148          22 : int linux_br_del(int sock, const char *brname)
     149             : {
     150          22 :         if (ioctl(sock, SIOCBRDELBR, brname) < 0) {
     151          13 :                 wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s",
     152          13 :                            brname, strerror(errno));
     153          13 :                 return -1;
     154             :         }
     155             : 
     156           9 :         return 0;
     157             : }
     158             : 
     159             : 
     160          35 : int linux_br_add_if(int sock, const char *brname, const char *ifname)
     161             : {
     162             :         struct ifreq ifr;
     163             :         int ifindex;
     164             : 
     165          35 :         ifindex = if_nametoindex(ifname);
     166          35 :         if (ifindex == 0)
     167           0 :                 return -1;
     168             : 
     169          35 :         os_memset(&ifr, 0, sizeof(ifr));
     170          35 :         os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
     171          35 :         ifr.ifr_ifindex = ifindex;
     172          35 :         if (ioctl(sock, SIOCBRADDIF, &ifr) < 0) {
     173           0 :                 wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge "
     174           0 :                            "%s: %s", ifname, brname, strerror(errno));
     175           0 :                 return -1;
     176             :         }
     177             : 
     178          35 :         return 0;
     179             : }
     180             : 
     181             : 
     182          36 : int linux_br_del_if(int sock, const char *brname, const char *ifname)
     183             : {
     184             :         struct ifreq ifr;
     185             :         int ifindex;
     186             : 
     187          36 :         ifindex = if_nametoindex(ifname);
     188          36 :         if (ifindex == 0)
     189           0 :                 return -1;
     190             : 
     191          36 :         os_memset(&ifr, 0, sizeof(ifr));
     192          36 :         os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
     193          36 :         ifr.ifr_ifindex = ifindex;
     194          36 :         if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) {
     195          24 :                 wpa_printf(MSG_DEBUG, "Could not remove interface %s from "
     196          24 :                            "bridge %s: %s", ifname, brname, strerror(errno));
     197          24 :                 return -1;
     198             :         }
     199             : 
     200          12 :         return 0;
     201             : }
     202             : 
     203             : 
     204        2039 : int linux_br_get(char *brname, const char *ifname)
     205             : {
     206             :         char path[128], brlink[128], *pos;
     207             :         ssize_t res;
     208             : 
     209        2039 :         os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge",
     210             :                     ifname);
     211        2039 :         res = readlink(path, brlink, sizeof(brlink));
     212        2039 :         if (res < 0 || (size_t) res >= sizeof(brlink))
     213        2036 :                 return -1;
     214           3 :         brlink[res] = '\0';
     215           3 :         pos = os_strrchr(brlink, '/');
     216           3 :         if (pos == NULL)
     217           0 :                 return -1;
     218           3 :         pos++;
     219           3 :         os_strlcpy(brname, pos, IFNAMSIZ);
     220           3 :         return 0;
     221             : }
     222             : 
     223             : 
     224        1970 : int linux_master_get(char *master_ifname, const char *ifname)
     225             : {
     226             :         char buf[128], masterlink[128], *pos;
     227             :         ssize_t res;
     228             : 
     229             :         /* check whether there is a master */
     230        1970 :         os_snprintf(buf, sizeof(buf), "/sys/class/net/%s/master", ifname);
     231             : 
     232        1970 :         res = readlink(buf, masterlink, sizeof(masterlink));
     233        1970 :         if (res < 0 || (size_t) res >= sizeof(masterlink))
     234        1970 :                 return -1;
     235             : 
     236           0 :         masterlink[res] = '\0';
     237             : 
     238           0 :         pos = os_strrchr(masterlink, '/');
     239           0 :         if (pos == NULL)
     240           0 :                 return -1;
     241           0 :         pos++;
     242           0 :         os_strlcpy(master_ifname, pos, IFNAMSIZ);
     243           0 :         return 0;
     244             : }

Generated by: LCOV version 1.10