iw.c (6041B)
1 /* 2 wificurse - WiFi Jamming tool 3 Copyright (C) 2012 oblique 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <stdlib.h> 20 #include <string.h> 21 #include <sys/socket.h> 22 #include <sys/ioctl.h> 23 #include <net/ethernet.h> 24 #include <netpacket/packet.h> 25 #include <linux/wireless.h> 26 #include "error.h" 27 #include "iw.h" 28 29 30 void iw_init_dev(struct iw_dev *dev) { 31 memset(dev, 0, sizeof(*dev)); 32 dev->fd_in = -1; 33 dev->fd_out = -1; 34 } 35 36 /* man 7 netdevice 37 * man 7 packet 38 */ 39 int iw_open(struct iw_dev *dev) { 40 struct ifreq ifr; 41 struct iwreq iwr; 42 struct sockaddr_ll sll; 43 struct packet_mreq mreq; 44 int fd; 45 46 fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 47 if (fd < 0) 48 return_error("socket"); 49 dev->fd_in = fd; 50 51 dev->fd_out = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 52 if (dev->fd_out < 0) 53 return_error("socket"); 54 55 /* save current interface flags */ 56 memset(&dev->old_flags, 0, sizeof(dev->old_flags)); 57 strncpy(dev->old_flags.ifr_name, dev->ifname, sizeof(dev->old_flags.ifr_name)-1); 58 if (ioctl(fd, SIOCGIFFLAGS, &dev->old_flags) < 0) { 59 dev->old_flags.ifr_name[0] = '\0'; 60 return_error("ioctl(SIOCGIFFLAGS)"); 61 } 62 63 /* save current interface mode */ 64 memset(&dev->old_mode, 0, sizeof(dev->old_mode)); 65 strncpy(dev->old_mode.ifr_name, dev->ifname, sizeof(dev->old_mode.ifr_name)-1); 66 if (ioctl(fd, SIOCGIWMODE, &dev->old_mode) < 0) { 67 dev->old_mode.ifr_name[0] = '\0'; 68 return_error("ioctl(SIOCGIWMODE)"); 69 } 70 71 /* set interface down (ifr_flags = 0) */ 72 memset(&ifr, 0, sizeof(ifr)); 73 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)-1); 74 if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) 75 return_error("ioctl(SIOCSIFFLAGS)"); 76 77 /* set monitor mode */ 78 memset(&iwr, 0, sizeof(iwr)); 79 strncpy(iwr.ifr_name, dev->ifname, sizeof(iwr.ifr_name)-1); 80 iwr.u.mode = IW_MODE_MONITOR; 81 if (ioctl(fd, SIOCSIWMODE, &iwr) < 0) 82 return_error("ioctl(SIOCSIWMODE)"); 83 84 /* set interface up, broadcast and running */ 85 ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING; 86 if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) 87 return_error("ioctl(SIOCSIFFLAGS)"); 88 89 /* get interface index */ 90 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) 91 return_error("ioctl(SIOCGIFINDEX)"); 92 dev->ifindex = ifr.ifr_ifindex; 93 94 /* bind interface to fd_in socket */ 95 memset(&sll, 0, sizeof(sll)); 96 sll.sll_family = AF_PACKET; 97 sll.sll_ifindex = dev->ifindex; 98 sll.sll_protocol = htons(ETH_P_ALL); 99 if (bind(dev->fd_in, (struct sockaddr*)&sll, sizeof(sll)) < 0) 100 return_error("bind(%s)", dev->ifname); 101 102 /* bind interface to fd_out socket */ 103 if (bind(dev->fd_out, (struct sockaddr*)&sll, sizeof(sll)) < 0) 104 return_error("bind(%s)", dev->ifname); 105 106 shutdown(dev->fd_in, SHUT_WR); 107 shutdown(dev->fd_out, SHUT_RD); 108 109 /* set fd_in in promiscuous mode */ 110 memset(&mreq, 0, sizeof(mreq)); 111 mreq.mr_ifindex = dev->ifindex; 112 mreq.mr_type = PACKET_MR_PROMISC; 113 if (setsockopt(dev->fd_in, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) 114 return_error("setsockopt(PACKET_MR_PROMISC)"); 115 116 return 0; 117 } 118 119 void iw_close(struct iw_dev *dev) { 120 struct ifreq ifr; 121 122 if (dev->fd_in == -1) 123 return; 124 125 if (dev->fd_out == -1) { 126 close(dev->fd_in); 127 return; 128 } 129 130 if (dev->old_flags.ifr_name[0] != '\0') { 131 /* set interface down (ifr_flags = 0) */ 132 memset(&ifr, 0, sizeof(ifr)); 133 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)-1); 134 ioctl(dev->fd_in, SIOCSIFFLAGS, &ifr); 135 /* restore old mode */ 136 if (dev->old_mode.ifr_name[0] != '\0') 137 ioctl(dev->fd_in, SIOCSIWMODE, &dev->old_mode); 138 /* restore old flags */ 139 ioctl(dev->fd_in, SIOCSIFFLAGS, &dev->old_flags); 140 } 141 142 close(dev->fd_in); 143 close(dev->fd_out); 144 } 145 146 ssize_t iw_write(struct iw_dev *dev, void *buf, size_t count) { 147 unsigned char *pbuf, *pkt; 148 struct radiotap_hdr *rt_hdr; 149 struct write_radiotap_data *w_rt_data; 150 ssize_t r; 151 152 pbuf = malloc(sizeof(*rt_hdr) + sizeof(*w_rt_data) + count); 153 if (pbuf == NULL) 154 return_error("malloc"); 155 156 rt_hdr = (struct radiotap_hdr*)pbuf; 157 w_rt_data = (struct write_radiotap_data*)(pbuf + sizeof(*rt_hdr)); 158 pkt = pbuf + sizeof(*rt_hdr) + sizeof(*w_rt_data); 159 160 /* radiotap header */ 161 memset(rt_hdr, 0, sizeof(*rt_hdr)); 162 rt_hdr->len = sizeof(*rt_hdr) + sizeof(*w_rt_data); 163 rt_hdr->present = RADIOTAP_F_PRESENT_RATE | RADIOTAP_F_PRESENT_TX_FLAGS; 164 /* radiotap fields */ 165 memset(w_rt_data, 0, sizeof(*w_rt_data)); 166 w_rt_data->rate = 2; /* 1 Mb/s */ 167 w_rt_data->tx_flags = RADIOTAP_F_TX_FLAGS_NOACK | RADIOTAP_F_TX_FLAGS_NOSEQ; 168 /* packet */ 169 memcpy(pkt, buf, count); 170 171 r = send(dev->fd_out, pbuf, rt_hdr->len + count, 0); 172 if (r < 0) { 173 free(pbuf); 174 return_error("send"); 175 } else if (r > 0) { 176 r -= rt_hdr->len; 177 if (r <= 0) 178 r = 0; 179 } 180 181 free(pbuf); 182 183 return r; 184 } 185 186 ssize_t iw_read(struct iw_dev *dev, void *buf, size_t count, uint8_t **pkt, size_t *pkt_sz) { 187 struct radiotap_hdr *rt_hdr; 188 int r; 189 190 *pkt = NULL; 191 *pkt_sz = 0; 192 193 /* read packet */ 194 r = recv(dev->fd_in, buf, count, 0); 195 if (r < 0) 196 return_error("recv"); 197 else if (r == 0) 198 return 0; 199 200 rt_hdr = buf; 201 if (sizeof(*rt_hdr) >= r || rt_hdr->len >= r) 202 return ERRNODATA; 203 204 *pkt = buf + rt_hdr->len; 205 *pkt_sz = r - rt_hdr->len; 206 207 return r; 208 } 209 210 int iw_set_channel(struct iw_dev *dev, int chan) { 211 struct iwreq iwr; 212 213 /* set channel */ 214 memset(&iwr, 0, sizeof(iwr)); 215 strncpy(iwr.ifr_name, dev->ifname, sizeof(iwr.ifr_name)-1); 216 iwr.u.freq.flags = IW_FREQ_FIXED; 217 iwr.u.freq.m = chan; 218 if (ioctl(dev->fd_in, SIOCSIWFREQ, &iwr) < 0) 219 return_error("ioctl(SIOCSIWFREQ)"); 220 dev->chan = chan; 221 222 return 0; 223 }