1 /*
2 * net library functions.
3 * Copyright (C) 2003, 2004, 2005, 2006 Mondru AB.
4 * Copyright (c) 2006-2008 David Bird <david@coova.com>
5 *
6 * The contents of this file may be used under the terms of the GNU
7 * General Public License Version 2, provided that the above copyright
8 * notice and this permission notice is included in all copies or
9 * substantial portions of the software.
10 *
11 */
12
13 #include "system.h"
14 #include "syserr.h"
15 #include "options.h"
16 #include "net.h"
17
dev_set_flags(char const * dev,int flags)18 int dev_set_flags(char const *dev, int flags) {
19 struct ifreq ifr;
20 int fd;
21
22 memset(&ifr, 0, sizeof(ifr));
23 ifr.ifr_flags = flags;
24 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
25 ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
26
27 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
28 log_err(errno,"socket() failed");
29 return -1;
30 }
31
32 if (ioctl(fd, SIOCSIFFLAGS, &ifr)) {
33 log_err(errno,"ioctl(SIOCSIFFLAGS) failed");
34 close(fd);
35 return -1;
36 }
37
38 close(fd);
39
40 return 0;
41 }
42
dev_get_flags(char const * dev,int * flags)43 int dev_get_flags(char const *dev, int *flags) {
44 struct ifreq ifr;
45 int fd;
46
47 memset(&ifr, 0, sizeof(ifr));
48 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
49 ifr.ifr_name[IFNAMSIZ-1] = 0;
50
51 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
52 log_err(errno, "socket() failed");
53 return -1;
54 }
55
56 if (ioctl(fd, SIOCGIFFLAGS, &ifr)) {
57 log_err(errno, "ioctl(SIOCSIFFLAGS) failed");
58 close(fd);
59 return -1;
60 }
61
62 close(fd);
63
64 *flags = ifr.ifr_flags;
65
66 return 0;
67 }
68
dev_set_address(char const * devname,struct in_addr * address,struct in_addr * dstaddr,struct in_addr * netmask)69 int dev_set_address(char const *devname, struct in_addr *address,
70 struct in_addr *dstaddr, struct in_addr *netmask) {
71 struct ifreq ifr;
72 int fd;
73
74 memset (&ifr, 0, sizeof (ifr));
75 ifr.ifr_addr.sa_family = AF_INET;
76 ifr.ifr_dstaddr.sa_family = AF_INET;
77
78 #if defined(__linux__)
79 ifr.ifr_netmask.sa_family = AF_INET;
80
81 #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
82 ((struct sockaddr_in *) &ifr.ifr_addr)->sin_len = sizeof (struct sockaddr_in);
83 ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_len = sizeof (struct sockaddr_in);
84 #endif
85
86 strncpy(ifr.ifr_name, devname, IFNAMSIZ);
87 ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
88
89 /* Create a channel to the NET kernel. */
90 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
91 log_err(errno, "socket() failed");
92 return -1;
93 }
94
95 if (address) { /* Set the interface address */
96 ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = address->s_addr;
97 if (ioctl(fd, SIOCSIFADDR, (void *) &ifr) < 0) {
98 if (errno != EEXIST) {
99 log_err(errno, "ioctl(SIOCSIFADDR) failed");
100 }
101 else {
102 log_warn(errno, "ioctl(SIOCSIFADDR): Address already exists");
103 }
104 close(fd);
105 return -1;
106 }
107 }
108
109 if (dstaddr) { /* Set the destination address */
110 ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = dstaddr->s_addr;
111 if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
112 log_err(errno, "ioctl(SIOCSIFDSTADDR) failed");
113 close(fd);
114 return -1;
115 }
116 }
117
118 if (netmask) { /* Set the netmask */
119 #if defined(__linux__)
120 ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = netmask->s_addr;
121
122 #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
123 ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = netmask->s_addr;
124
125 #elif defined(__sun__)
126 ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = netmask->s_addr;
127 #else
128 #error "Unknown platform!"
129 #endif
130
131 if (ioctl(fd, SIOCSIFNETMASK, (void *) &ifr) < 0) {
132 log_err(errno, "ioctl(SIOCSIFNETMASK) failed");
133 close(fd);
134 return -1;
135 }
136 }
137
138 close(fd);
139
140 return dev_set_flags(devname, IFF_UP | IFF_RUNNING);
141 }
142
net_init(net_interface * netif,char * ifname,uint16_t protocol,int promisc,uint8_t * mac)143 int net_init(net_interface *netif, char *ifname, uint16_t protocol, int promisc, uint8_t *mac) {
144 memset(netif, 0, sizeof(net_interface));
145 strncpy(netif->devname, ifname, IFNAMSIZ);
146 netif->devname[IFNAMSIZ] = 0;
147 netif->protocol = protocol;
148
149 if (promisc) netif->flags |= NET_PROMISC;
150
151 if (mac) {
152 netif->flags |= NET_USEMAC;
153 memcpy(netif->hwaddr, mac, PKT_ETH_ALEN);
154 }
155
156 return net_open(netif);
157 }
158
net_open(net_interface * netif)159 int net_open(net_interface *netif) {
160 net_close(netif);
161 net_gflags(netif);
162
163 if (!(netif->devflags & IFF_UP) || !(netif->devflags & IFF_RUNNING)) {
164 struct in_addr noaddr;
165 net_sflags(netif, netif->devflags | IFF_NOARP);
166 memset(&noaddr, 0, sizeof(noaddr));
167 dev_set_address(netif->devname, &noaddr, NULL, NULL);
168 }
169
170 return net_open_eth(netif);
171 }
172
net_reopen(net_interface * netif)173 int net_reopen(net_interface *netif) {
174 net_close(netif);
175 return net_open(netif);
176 }
177
net_set_address(net_interface * netif,struct in_addr * address,struct in_addr * dstaddr,struct in_addr * netmask)178 int net_set_address(net_interface *netif, struct in_addr *address,
179 struct in_addr *dstaddr, struct in_addr *netmask) {
180 netif->address.s_addr = address->s_addr;
181 netif->gateway.s_addr = dstaddr->s_addr;
182 netif->netmask.s_addr = netmask->s_addr;
183
184 return dev_set_address(netif->devname, address, dstaddr, netmask);
185 }
186
net_read(net_interface * netif,void * d,size_t dlen)187 ssize_t net_read(net_interface *netif, void *d, size_t dlen) {
188 ssize_t len;
189
190 if ((len = read(netif->fd, d, dlen)) < 0) {
191 #ifdef ENETDOWN
192 if (errno == ENETDOWN) {
193 net_reopen(netif);
194 }
195 #endif
196 log_err(errno, "read(fd=%d, len=%d) == %d", netif->fd, dlen, len);
197 return -1;
198 }
199
200 return len;
201 }
202
net_write(net_interface * netif,void * d,size_t dlen)203 ssize_t net_write(net_interface *netif, void *d, size_t dlen) {
204 ssize_t len;
205
206 if ((len = write(netif->fd, d, dlen)) < 0) {
207 #ifdef ENETDOWN
208 if (errno == ENETDOWN) {
209 net_reopen(netif);
210 }
211 #endif
212 log_err(errno, "write(fd=%d, len=%d) failed", netif->fd, dlen);
213 return -1;
214 }
215
216 return len;
217 }
218
net_route(struct in_addr * dst,struct in_addr * gateway,struct in_addr * mask,int delete)219 int net_route(struct in_addr *dst, struct in_addr *gateway, struct in_addr *mask, int delete) {
220
221 /* TODO: solaris! */
222
223 #if defined(__linux__)
224 struct rtentry r;
225 int fd;
226
227 memset (&r, 0, sizeof (r));
228 r.rt_flags = RTF_UP | RTF_GATEWAY; /* RTF_HOST not set */
229
230 /* Create a channel to the NET kernel. */
231 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
232 log_err(errno, "socket() failed");
233 return -1;
234 }
235
236 r.rt_dst.sa_family = AF_INET;
237 r.rt_gateway.sa_family = AF_INET;
238 r.rt_genmask.sa_family = AF_INET;
239 ((struct sockaddr_in *) &r.rt_dst)->sin_addr.s_addr = dst->s_addr;
240 ((struct sockaddr_in *) &r.rt_gateway)->sin_addr.s_addr = gateway->s_addr;
241 ((struct sockaddr_in *) &r.rt_genmask)->sin_addr.s_addr = mask->s_addr;
242
243 if (delete) {
244 if (ioctl(fd, SIOCDELRT, (void *) &r) < 0) {
245 log_err(errno,"ioctl(SIOCDELRT) failed");
246 close(fd);
247 return -1;
248 }
249 }
250 else {
251 if (ioctl(fd, SIOCADDRT, (void *) &r) < 0) {
252 log_err(errno, "ioctl(SIOCADDRT) failed");
253 close(fd);
254 return -1;
255 }
256 }
257 close(fd);
258 return 0;
259
260 #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
261
262 struct {
263 struct rt_msghdr rt;
264 struct sockaddr_in dst;
265 struct sockaddr_in gate;
266 struct sockaddr_in mask;
267 } req;
268
269 int fd;
270 struct rt_msghdr *rtm;
271
272 if ((fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
273 log_err(errno, "socket() failed");
274 return -1;
275 }
276
277 memset(&req, 0, sizeof(req));
278
279 rtm = &req.rt;
280
281 rtm->rtm_msglen = sizeof(req);
282 rtm->rtm_version = RTM_VERSION;
283 if (delete) {
284 rtm->rtm_type = RTM_DELETE;
285 }
286 else {
287 rtm->rtm_type = RTM_ADD;
288 }
289 rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; /* TODO */
290 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
291 rtm->rtm_pid = getpid();
292 rtm->rtm_seq = 0044; /* TODO */
293
294 req.dst.sin_family = AF_INET;
295 req.dst.sin_len = sizeof(req.dst);
296 req.mask.sin_family = AF_INET;
297 req.mask.sin_len = sizeof(req.mask);
298 req.gate.sin_family = AF_INET;
299 req.gate.sin_len = sizeof(req.gate);
300
301 req.dst.sin_addr.s_addr = dst->s_addr;
302 req.mask.sin_addr.s_addr = mask->s_addr;
303 req.gate.sin_addr.s_addr = gateway->s_addr;
304
305 if (write(fd, rtm, rtm->rtm_msglen) < 0) {
306 log_err(errno, "write() failed");
307 close(fd);
308 return -1;
309 }
310 close(fd);
311 return 0;
312
313 #elif defined(__sun__)
314 log_err(errno, "Could not set up routing on Solaris. Please add route manually.");
315 return 0;
316 #else
317 #error "Unknown platform!"
318 #endif
319 }
320
321 #if defined(__linux__)
322
323 /**
324 * Opens an Ethernet interface. As an option the interface can be set in
325 * promisc mode. If not null macaddr and ifindex are filled with the
326 * interface mac address and index
327 **/
net_open_eth(net_interface * netif)328 int net_open_eth(net_interface *netif) {
329 struct ifreq ifr;
330 struct packet_mreq mr;
331 struct sockaddr_ll sa;
332 int option = 1;
333
334 memset(&ifr, 0, sizeof(ifr));
335
336 /* Create socket */
337 if ((netif->fd = socket(PF_PACKET, SOCK_RAW, htons(netif->protocol))) < 0) {
338 if (errno == EPERM) {
339 log_err(errno, "Cannot create raw socket. Must be root.");
340 }
341
342 log_err(errno, "socket(domain=%d, type=%lx, protocol=%d) failed",
343 PF_PACKET, SOCK_RAW, netif->protocol);
344
345 return -1;
346 }
347
348 /* Enable reception and transmission of broadcast frames */
349 if (setsockopt(netif->fd, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option)) < 0) {
350 log_err(errno, "setsockopt(s=%d, level=%d, optname=%d, optlen=%d) failed",
351 netif->fd, SOL_SOCKET, SO_BROADCAST, sizeof(option));
352 return -1;
353 }
354
355 /* Get the MAC address of our interface */
356 strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
357 if (ioctl(netif->fd, SIOCGIFHWADDR, &ifr) < 0) {
358 log_err(errno, "ioctl(d=%d, request=%d) failed", netif->fd, SIOCGIFHWADDR);
359 return -1;
360 }
361
362 if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
363
364 netif->flags |= NET_ETHHDR;
365
366 if ((netif->flags & NET_USEMAC) == 0)
367 memcpy(netif->hwaddr, ifr.ifr_hwaddr.sa_data, PKT_ETH_ALEN);
368 }
369
370 if (netif->hwaddr[0] & 0x01) {
371 log_err(0, "Ethernet has broadcast or multicast address: %.16s", netif->devname);
372 }
373
374 /* Get the current interface address, network, and any destination address */
375
376 /* Verify that MTU = ETH_DATA_LEN */
377 strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
378 if (ioctl(netif->fd, SIOCGIFMTU, &ifr) < 0) {
379 log_err(errno, "ioctl(d=%d, request=%d) failed", netif->fd, SIOCGIFMTU);
380 return -1;
381 }
382 if (ifr.ifr_mtu != ETH_DATA_LEN) {
383 log_err(0, "MTU does not match EHT_DATA_LEN: %d %d", ifr.ifr_mtu, ETH_DATA_LEN);
384 return -1;
385 }
386
387 /* Get ifindex */
388 strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
389 if (ioctl(netif->fd, SIOCGIFINDEX, &ifr) < 0) {
390 log_err(errno, "ioctl(SIOCFIGINDEX) failed");
391 }
392 netif->ifindex = ifr.ifr_ifindex;
393
394 /* Set interface in promisc mode */
395 if (netif->flags & NET_PROMISC) {
396 memset(&mr,0,sizeof(mr));
397 mr.mr_ifindex = ifr.ifr_ifindex;
398 mr.mr_type = PACKET_MR_PROMISC;
399 if (setsockopt(netif->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (char *)&mr, sizeof(mr)) < 0) {
400 log_err(errno, "setsockopt(s=%d, level=%d, optname=%d, optlen=%d) failed",
401 netif->fd, SOL_SOCKET, PACKET_ADD_MEMBERSHIP, sizeof(mr));
402 return -1;
403 }
404 }
405
406 /* Bind to particular interface */
407 memset(&sa, 0, sizeof(sa));
408 sa.sll_family = AF_PACKET;
409 sa.sll_protocol = htons(netif->protocol);
410 sa.sll_ifindex = ifr.ifr_ifindex;
411
412 if (bind(netif->fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
413 log_err(errno, "bind(sockfd=%d) failed", netif->fd);
414 return -1;
415 }
416
417 return 0;
418 }
419
420 #elif defined (__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
421
net_getmac(const char * ifname,char * macaddr)422 int net_getmac(const char *ifname, char *macaddr) {
423
424 struct ifaddrs *ifap, *ifa;
425 struct sockaddr_dl *sdl;
426
427 if (getifaddrs(&ifap)) {
428 log_err(errno, "getifaddrs() failed!");
429 return -1;
430 }
431
432 ifa = ifap;
433 while (ifa) {
434 if ((strcmp(ifa->ifa_name, ifname) == 0) &&
435 (ifa->ifa_addr->sa_family == AF_LINK)) {
436 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
437 switch(sdl->sdl_type) {
438 case IFT_ETHER:
439 #ifdef IFT_IEEE80211
440 case IFT_IEEE80211:
441 #endif
442 break;
443 default:
444 continue;
445 }
446 if (sdl->sdl_alen != PKT_ETH_ALEN) {
447 log_err(errno, "Wrong sdl_alen!");
448 freeifaddrs(ifap);
449 return -1;
450 }
451 memcpy(macaddr, LLADDR(sdl), PKT_ETH_ALEN);
452 freeifaddrs(ifap);
453 return 0;
454 }
455 ifa = ifa->ifa_next;
456 }
457 freeifaddrs(ifap);
458 return -1;
459 }
460
461 /**
462 * Opens an Ethernet interface. As an option the interface can be set in
463 * promisc mode. If not null macaddr and ifindex are filled with the
464 * interface mac address and index
465 **/
466
467 /* Relevant IOCTLs
468 FIONREAD Get the number of bytes in input buffer
469 SIOCGIFADDR Get interface address (IP)
470 BIOCGBLEN, BIOCSBLEN Get and set required buffer length
471 BIOCGDLT Type of underlying data interface
472 BIOCPROMISC Set in promisc mode
473 BIOCFLUSH Flushes the buffer of incoming packets
474 BIOCGETIF, BIOCSETIF Set hardware interface. Uses ift_name
475 BIOCSRTIMEOUT, BIOCGRTIMEOUT Set and get timeout for reads
476 BIOCGSTATS Return stats for the interface
477 BIOCIMMEDIATE Return immediately from reads as soon as packet arrives.
478 BIOCSETF Set filter
479 BIOCVERSION Return the version of BPF
480 BIOCSHDRCMPLT BIOCGHDRCMPLT Set flag of wheather to fill in MAC address
481 BIOCSSEESENT BIOCGSEESENT Return locally generated packets */
482
net_open_eth(net_interface * netif)483 int net_open_eth(net_interface *netif) {
484 char devname[IFNAMSIZ+5]; /* "/dev/" + ifname */
485 int devnum;
486 struct ifreq ifr;
487 struct ifaliasreq areq;
488 int local_fd;
489 struct bpf_version bv;
490
491 u_int32_t ipaddr;
492 struct sockaddr_dl hwaddr;
493 unsigned int value;
494
495 /* Find suitable device */
496 for (devnum = 0; devnum < 255; devnum++) { /* TODO 255 */
497 snprintf(devname, sizeof(devname), "/dev/bpf%d", devnum);
498 devname[sizeof(devname)] = 0;
499 if ((netif->fd = open(devname, O_RDWR)) >= 0) break;
500 if (errno != EBUSY) break;
501 }
502 if (netif->fd < 0) {
503 log_err(errno, "Can't find bpf device");
504 return -1;
505 }
506
507 /* Set the interface */
508 memset(&ifr, 0, sizeof(ifr));
509 strncpy(ifr.ifr_name, netif->devname, sizeof(ifr.ifr_name));
510 if (ioctl(netif->fd, BIOCSETIF, &ifr) < 0) {
511 log_err(errno,"ioctl() failed");
512 return -1;
513 }
514
515 /* Get and validate BPF version */
516 if (ioctl(netif->fd, BIOCVERSION, &bv) < 0) {
517 log_err(errno,"ioctl() failed!");
518 return -1;
519 }
520 if (bv.bv_major != BPF_MAJOR_VERSION ||
521 bv.bv_minor < BPF_MINOR_VERSION) {
522 log_err(errno,"wrong BPF version!");
523 return -1;
524 }
525
526 /* Get the MAC address of our interface */
527 if (net_getmac(netif->devname, netif->hwaddr)) {
528 log_err(0,"Did not find MAC address!");
529 }
530 else {
531 netif->flags |= NET_ETHHDR;
532 }
533
534 if (netif->hwaddr[0] & 0x01) {
535 log_err(0, "Ethernet has broadcast or multicast address: %.16s", netif->devname);
536 return -1;
537 }
538
539 /* Set interface in promisc mode */
540 if (netif->flags & NET_PROMISC) {
541 value = 1;
542 if (ioctl(netif->fd, BIOCPROMISC, NULL) < 0) {
543 log_err(errno,"ioctl() failed!");
544 return -1;
545 }
546 value = 1;
547 if (ioctl(netif->fd, BIOCSHDRCMPLT, &value) < 0) {
548 log_err(errno,"ioctl() failed!");
549 return -1;
550 }
551 }
552 else {
553 value = 0;
554 if (ioctl(netif->fd, BIOCSHDRCMPLT, &value) < 0) {
555 log_err(errno,"ioctl() failed!");
556 return -1;
557 }
558 }
559
560 /* Make sure reads return as soon as packet has been received */
561 value = 1;
562 if (ioctl(netif->fd, BIOCIMMEDIATE, &value) < 0) {
563 log_err(errno,"ioctl() failed!");
564 return -1;
565 }
566
567 return 0;
568 }
569
570 #endif
571
572