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 1443382998 Lines: 86 117 73.5 %
Date: 2015-09-27 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        4655 : int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
      19             : {
      20             :         struct ifreq ifr;
      21             :         int ret;
      22             : 
      23        4655 :         if (sock < 0)
      24           0 :                 return -1;
      25             : 
      26        4655 :         os_memset(&ifr, 0, sizeof(ifr));
      27        4655 :         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
      28             : 
      29        4655 :         if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
      30          40 :                 ret = errno ? -errno : -999;
      31          40 :                 wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
      32          40 :                            ifname, strerror(errno));
      33          40 :                 return ret;
      34             :         }
      35             : 
      36        4615 :         if (dev_up) {
      37        2327 :                 if (ifr.ifr_flags & IFF_UP)
      38          22 :                         return 0;
      39        2305 :                 ifr.ifr_flags |= IFF_UP;
      40             :         } else {
      41        2288 :                 if (!(ifr.ifr_flags & IFF_UP))
      42          59 :                         return 0;
      43        2229 :                 ifr.ifr_flags &= ~IFF_UP;
      44             :         }
      45             : 
      46        4534 :         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        4534 :         return 0;
      55             : }
      56             : 
      57             : 
      58        2720 : int linux_iface_up(int sock, const char *ifname)
      59             : {
      60             :         struct ifreq ifr;
      61             :         int ret;
      62             : 
      63        2720 :         if (sock < 0)
      64           0 :                 return -1;
      65             : 
      66        2720 :         os_memset(&ifr, 0, sizeof(ifr));
      67        2720 :         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
      68             : 
      69        2720 :         if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
      70          11 :                 ret = errno ? -errno : -999;
      71          11 :                 wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
      72          11 :                            ifname, strerror(errno));
      73          11 :                 return ret;
      74             :         }
      75             : 
      76        2709 :         return !!(ifr.ifr_flags & IFF_UP);
      77             : }
      78             : 
      79             : 
      80        4135 : int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr)
      81             : {
      82             :         struct ifreq ifr;
      83             : 
      84        4135 :         os_memset(&ifr, 0, sizeof(ifr));
      85        4135 :         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
      86        4135 :         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        4135 :         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        4135 :         os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
      98             : 
      99        4135 :         return 0;
     100             : }
     101             : 
     102             : 
     103         207 : int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr)
     104             : {
     105             :         struct ifreq ifr;
     106             : 
     107         207 :         os_memset(&ifr, 0, sizeof(ifr));
     108         207 :         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
     109         207 :         os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
     110         207 :         ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
     111             : 
     112         207 :         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         207 :         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          12 : int linux_br_add(int sock, const char *brname)
     137             : {
     138          12 :         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          12 :         return 0;
     145             : }
     146             : 
     147             : 
     148          12 : int linux_br_del(int sock, const char *brname)
     149             : {
     150          12 :         if (ioctl(sock, SIOCBRDELBR, brname) < 0) {
     151          10 :                 wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s",
     152          10 :                            brname, strerror(errno));
     153          10 :                 return -1;
     154             :         }
     155             : 
     156           2 :         return 0;
     157             : }
     158             : 
     159             : 
     160          20 : int linux_br_add_if(int sock, const char *brname, const char *ifname)
     161             : {
     162             :         struct ifreq ifr;
     163             :         int ifindex;
     164             : 
     165          20 :         ifindex = if_nametoindex(ifname);
     166          20 :         if (ifindex == 0)
     167           0 :                 return -1;
     168             : 
     169          20 :         os_memset(&ifr, 0, sizeof(ifr));
     170          20 :         os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
     171          20 :         ifr.ifr_ifindex = ifindex;
     172          20 :         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          20 :         return 0;
     179             : }
     180             : 
     181             : 
     182          21 : int linux_br_del_if(int sock, const char *brname, const char *ifname)
     183             : {
     184             :         struct ifreq ifr;
     185             :         int ifindex;
     186             : 
     187          21 :         ifindex = if_nametoindex(ifname);
     188          21 :         if (ifindex == 0)
     189           0 :                 return -1;
     190             : 
     191          21 :         os_memset(&ifr, 0, sizeof(ifr));
     192          21 :         os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ);
     193          21 :         ifr.ifr_ifindex = ifindex;
     194          21 :         if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) {
     195          18 :                 wpa_printf(MSG_DEBUG, "Could not remove interface %s from "
     196          18 :                            "bridge %s: %s", ifname, brname, strerror(errno));
     197          18 :                 return -1;
     198             :         }
     199             : 
     200           3 :         return 0;
     201             : }
     202             : 
     203             : 
     204        1658 : int linux_br_get(char *brname, const char *ifname)
     205             : {
     206             :         char path[128], brlink[128], *pos;
     207             :         ssize_t res;
     208             : 
     209        1658 :         os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge",
     210             :                     ifname);
     211        1658 :         res = readlink(path, brlink, sizeof(brlink));
     212        1658 :         if (res < 0 || (size_t) res >= sizeof(brlink))
     213        1655 :                 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        1619 : 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        1619 :         os_snprintf(buf, sizeof(buf), "/sys/class/net/%s/master", ifname);
     231             : 
     232        1619 :         res = readlink(buf, masterlink, sizeof(masterlink));
     233        1619 :         if (res < 0 || (size_t) res >= sizeof(masterlink))
     234        1619 :                 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