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

Generated by: LCOV version 1.10