3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of olsr.org, olsrd nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Visit http://www.olsr.org for more information.
36 * If you find this software useful feel free to make a donation
37 * to the project. For more information see the website or contact
38 * the copyright holders.
46 #include "../net_os.h"
47 #include "../ipcalc.h"
52 #include <sys/ioctl.h>
60 #define IPV6_ADDR_LOOPBACK 0x0010U
61 #define IPV6_ADDR_LINKLOCAL 0x0020U
62 #define IPV6_ADDR_SITELOCAL 0x0040U
64 /* Redirect proc entry */
65 #define REDIRECT_PROC "/proc/sys/net/ipv4/conf/%s/send_redirects"
67 /* IP spoof proc entry */
68 #define SPOOF_PROC "/proc/sys/net/ipv4/conf/%s/rp_filter"
70 /* list of IPv6 interfaces */
71 #define PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
74 *Wireless definitions for ioctl calls
75 *(from linux/wireless.h)
77 #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
78 #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */
80 /* The original state of the IP forwarding proc entry */
81 static char orig_fwd_state;
82 static char orig_global_redirect_state;
85 *Bind a socket to a device
87 *@param sock the socket to bind
88 *@param dev_name name of the device
90 *@return negative if error
94 bind_socket_to_device(int sock, char *dev_name)
97 *Bind to device using the SO_BINDTODEVICE flag
99 OLSR_PRINTF(3, "Binding socket %d to device %s\n", sock, dev_name);
100 return setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, dev_name, strlen(dev_name) + 1);
104 *Enable IP forwarding.
105 *Just writing "1" to the /proc/sys/net/ipv4/ip_forward
106 *if using IPv4 or /proc/sys/net/ipv6/conf/all/forwarding
108 *Could probably drop the check for
109 *"0" here and write "1" anyways.
111 *@param version IP version.
113 *@return 1 on sucess 0 on failiure
116 enable_ip_forwarding(int version)
119 const char *const procfile = version == AF_INET ? "/proc/sys/net/ipv4/ip_forward" : "/proc/sys/net/ipv6/conf/all/forwarding";
121 if ((proc_fwd = fopen(procfile, "r")) == NULL) {
123 if (version == AF_INET)
125 "WARNING! Could not open the %s file to check/enable IP forwarding!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n",
130 "WARNING! Could not open the %s file to check/enable IP forwarding!\nAre you using the procfile filesystem?\nDoes your system support IPv6?\nI will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n",
133 olsr_startup_sleep(3);
137 orig_fwd_state = fgetc(proc_fwd);
139 if (orig_fwd_state == '1') {
140 OLSR_PRINTF(3, "\nIP forwarding is enabled on this system\n");
142 if ((proc_fwd = fopen(procfile, "w")) == NULL) {
143 fprintf(stderr, "Could not open %s for writing!\n", procfile);
144 fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n");
145 olsr_startup_sleep(3);
148 syslog(LOG_INFO, "Writing \"1\" to %s\n", procfile);
149 fputs("1", proc_fwd);
157 disable_redirects_global(int version)
160 const char *const procfile = "/proc/sys/net/ipv4/conf/all/send_redirects";
162 if (version == AF_INET6)
165 if ((proc_redirect = fopen(procfile, "r")) == NULL) {
167 "WARNING! Could not open the %s file to check/disable ICMP redirects!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that ICMP redirects are disabled!\n\n",
170 olsr_startup_sleep(3);
173 orig_global_redirect_state = fgetc(proc_redirect);
174 fclose(proc_redirect);
176 if (orig_global_redirect_state == '0')
179 if ((proc_redirect = fopen(procfile, "w")) == NULL) {
180 fprintf(stderr, "Could not open %s for writing!\n", procfile);
181 fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that ICMP redirect is disabeled!\n\n");
182 olsr_startup_sleep(3);
185 syslog(LOG_INFO, "Writing \"0\" to %s", procfile);
186 fputs("0", proc_redirect);
187 fclose(proc_redirect);
193 *@return 1 on sucess 0 on failiure
196 disable_redirects(const char *if_name, struct interface *iface, int version)
199 char procfile[FILENAME_MAX];
201 if (version == AF_INET6)
204 /* Generate the procfile name */
205 snprintf(procfile, sizeof(procfile), REDIRECT_PROC, if_name);
207 if ((proc_redirect = fopen(procfile, "r")) == NULL) {
209 "WARNING! Could not open the %s file to check/disable ICMP redirects!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that ICMP redirects are disabled!\n\n",
211 olsr_startup_sleep(3);
214 iface->nic_state.redirect = fgetc(proc_redirect);
215 fclose(proc_redirect);
217 if ((proc_redirect = fopen(procfile, "w")) == NULL) {
218 fprintf(stderr, "Could not open %s for writing!\n", procfile);
219 fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that ICMP redirect is disabeled!\n\n");
220 olsr_startup_sleep(3);
223 syslog(LOG_INFO, "Writing \"0\" to %s", procfile);
224 fputs("0", proc_redirect);
225 fclose(proc_redirect);
231 *@return 1 on sucess 0 on failiure
234 deactivate_spoof(const char *if_name, struct interface *iface, int version)
237 char procfile[FILENAME_MAX];
239 if (version == AF_INET6)
242 /* Generate the procfile name */
243 sprintf(procfile, SPOOF_PROC, if_name);
245 if ((proc_spoof = fopen(procfile, "r")) == NULL) {
247 "WARNING! Could not open the %s file to check/disable the IP spoof filter!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that IP spoof filtering is disabled!\n\n",
250 olsr_startup_sleep(3);
253 iface->nic_state.spoof = fgetc(proc_spoof);
256 if ((proc_spoof = fopen(procfile, "w")) == NULL) {
257 fprintf(stderr, "Could not open %s for writing!\n", procfile);
258 fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that IP spoof filtering is disabeled!\n\n");
259 olsr_startup_sleep(3);
262 syslog(LOG_INFO, "Writing \"0\" to %s", procfile);
263 fputs("0", proc_spoof);
269 *Resets the spoof filter and ICMP redirect settings
272 restore_settings(int version)
274 struct interface *ifs;
276 OLSR_PRINTF(1, "Restoring network state\n");
278 /* Restore IP forwarding to "off" */
279 if (orig_fwd_state == '0') {
280 const char *const procfile = version == AF_INET ? "/proc/sys/net/ipv4/ip_forward" : "/proc/sys/net/ipv6/conf/all/forwarding";
283 if ((proc_fd = fopen(procfile, "w")) == NULL) {
284 fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
286 syslog(LOG_INFO, "Resetting %s to %c\n", procfile, orig_fwd_state);
287 fputc(orig_fwd_state, proc_fd);
292 /* Restore global ICMP redirect setting */
293 if (orig_global_redirect_state != '0') {
294 if (version == AF_INET) {
295 const char *const procfile = "/proc/sys/net/ipv4/conf/all/send_redirects";
298 if ((proc_fd = fopen(procfile, "w")) == NULL) {
299 fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
301 syslog(LOG_INFO, "Resetting %s to %c\n", procfile, orig_global_redirect_state);
302 fputc(orig_global_redirect_state, proc_fd);
308 if (version == AF_INET6)
311 for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
312 char procfile[FILENAME_MAX];
314 /* Discard host-emulation interfaces */
319 /* Generate the procfile name */
320 snprintf(procfile, sizeof(procfile), REDIRECT_PROC, ifs->int_name);
322 if ((proc_fd = fopen(procfile, "w")) == NULL)
323 fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
325 syslog(LOG_INFO, "Resetting %s to %c\n", procfile, ifs->nic_state.redirect);
327 fputc(ifs->nic_state.redirect, proc_fd);
333 /* Generate the procfile name */
334 sprintf(procfile, SPOOF_PROC, ifs->int_name);
335 if ((proc_fd = fopen(procfile, "w")) == NULL)
336 fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile);
338 syslog(LOG_INFO, "Resetting %s to %c\n", procfile, ifs->nic_state.spoof);
340 fputc(ifs->nic_state.spoof, proc_fd);
348 *Creates a blocking tcp socket for communication with switch daemon.
349 *@param sa sockaddr struct. Used for bind(2).
350 *@return the FD of the socket or -1 on error.
353 gethemusocket(struct sockaddr_in *pin)
357 OLSR_PRINTF(1, " Connecting to switch daemon port 10150...");
358 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
360 syslog(LOG_ERR, "hcsocket: %m");
364 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
365 perror("SO_REUSEADDR failed");
369 /* connect to PORT on HOST */
370 if (connect(sock, (struct sockaddr *)pin, sizeof(*pin)) < 0) {
372 fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
373 printf("connection refused\n");
380 /* Keep TCP socket blocking */
385 *Creates a nonblocking broadcast socket.
386 *@param sa sockaddr struct. Used for bind(2).
387 *@return the FD of the socket or -1 on error.
390 getsocket(int bufspace, struct interface *ifp)
392 struct sockaddr_in sin;
394 int sock = socket(AF_INET, SOCK_DGRAM, 0);
397 syslog(LOG_ERR, "socket: %m");
403 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
404 perror("setsockopt");
405 syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
411 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
412 perror("SO_REUSEADDR failed");
418 for (on = bufspace;; on -= 1024) {
419 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) == 0)
421 if (on <= 8 * 1024) {
422 perror("setsockopt");
423 syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
431 * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
435 if (bind_socket_to_device(sock, ifp->int_name) < 0) {
436 fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
437 syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
442 memset(&sin, 0, sizeof(sin));
443 sin.sin_family = AF_INET;
444 sin.sin_port = htons(olsr_cnf->olsrport);
447 sin.sin_addr.s_addr = ifp->int_addr.sin_addr.s_addr;
450 if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
452 syslog(LOG_ERR, "bind: %m");
457 on = fcntl(sock, F_GETFL);
459 syslog(LOG_ERR, "fcntl (F_GETFL): %m\n");
461 if (fcntl(sock, F_SETFL, on | O_NONBLOCK) == -1) {
462 syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
469 *Creates a nonblocking IPv6 socket
470 *@param sin sockaddr_in6 struct. Used for bind(2).
471 *@return the FD of the socket or -1 on error.
474 getsocket6(int bufspace, struct interface *ifp)
476 struct sockaddr_in6 sin;
478 int sock = socket(AF_INET6, SOCK_DGRAM, 0);
481 syslog(LOG_ERR, "socket: %m");
486 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
487 perror("setsockopt(IPV6_V6ONLY)");
488 syslog(LOG_ERR, "setsockopt(IPV6_V6ONLY): %m");
492 //#ifdef SO_BROADCAST
494 if (setsockopt(sock, SOL_SOCKET, SO_MULTICAST, &on, sizeof (on)) < 0)
496 perror("setsockopt");
497 syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
506 for (on = bufspace;; on -= 1024) {
507 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) == 0)
509 if (on <= 8 * 1024) {
510 perror("setsockopt");
511 syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
518 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
519 perror("SO_REUSEADDR failed");
525 * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!!
529 if (bind_socket_to_device(sock, ifp->int_name) < 0) {
530 fprintf(stderr, "Could not bind socket to device... exiting!\n\n");
531 syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n");
536 memset(&sin, 0, sizeof(sin));
537 sin.sin6_family = AF_INET6;
538 sin.sin6_port = htons(olsr_cnf->olsrport);
541 memcpy(&sin.sin6_addr, &ifp->int6_addr.sin6_addr, sizeof(struct in6_addr));
544 if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
546 syslog(LOG_ERR, "bind: %m");
551 on = fcntl(sock, F_GETFL);
553 syslog(LOG_ERR, "fcntl (F_GETFL): %m\n");
555 if (fcntl(sock, F_SETFL, on | O_NONBLOCK) == -1) {
556 syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
563 join_mcast(struct interface *ifs, int sock)
565 /* See linux/in6.h */
566 struct ipaddr_str buf;
567 struct ipv6_mreq mcastreq;
569 mcastreq.ipv6mr_multiaddr = ifs->int6_multaddr.sin6_addr;
570 mcastreq.ipv6mr_interface = ifs->if_index;
572 #if !defined __FreeBSD__ && !defined __FreeBSD_kernel__ && !defined __MacOSX__ && !defined __NetBSD__
573 OLSR_PRINTF(3, "Interface %s joining multicast %s...", ifs->int_name, ip6_to_string(&buf, &ifs->int6_multaddr.sin6_addr));
575 if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mcastreq, sizeof(struct ipv6_mreq)) < 0) {
576 perror("Join multicast");
580 #warning implement IPV6_ADD_MEMBERSHIP
584 #ifdef IPV6_JOIN_GROUP
585 /* Join reciever group */
586 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mcastreq, sizeof(struct ipv6_mreq)) < 0)
588 /* Join reciever group */
589 if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mcastreq, sizeof(struct ipv6_mreq)) < 0)
592 perror("Join multicast send");
596 if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&mcastreq.ipv6mr_interface, sizeof(mcastreq.ipv6mr_interface)) < 0) {
597 perror("Set multicast if");
601 OLSR_PRINTF(3, "OK\n");
606 *From net-tools lib/interface.c
610 get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, struct olsr_ip_prefix *prefix)
612 char addr6[40], devname[IFNAMSIZ];
614 int plen, scope, dad_status, if_idx;
616 union olsr_ip_addr tmp_ip;
618 if ((f = fopen(PATH_PROCNET_IFINET6, "r")) != NULL) {
620 (f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
621 addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
622 if (!strcmp(devname, ifname)) {
623 bool isNetWide = false;
624 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6],
626 OLSR_PRINTF(5, "\tinet6 addr: %s\n", addr6);
627 OLSR_PRINTF(5, "\tScope: %d\n", scope);
629 inet_pton(AF_INET6, addr6, &tmp_ip.v6);
631 isNetWide = (scope != IPV6_ADDR_LOOPBACK) && (scope != IPV6_ADDR_LINKLOCAL) && (scope != IPV6_ADDR_SITELOCAL);
633 if ((prefix == NULL && isNetWide) || (prefix != NULL && ip_in_net(&tmp_ip, prefix))) {
634 OLSR_PRINTF(4, "Found addr: %s:%s:%s:%s:%s:%s:%s:%s\n", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5],
635 addr6p[6], addr6p[7]);
636 memcpy(&saddr6->sin6_addr, &tmp_ip.v6, sizeof(struct in6_addr));
648 * Wrapper for sendto(2)
651 olsr_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr * to, socklen_t tolen)
653 return sendto(s, buf, len, flags, to, tolen);
657 * Wrapper for recvfrom(2)
661 olsr_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr * from, socklen_t * fromlen)
663 return recvfrom(s, buf, len, flags, from, fromlen);
667 * Wrapper for select(2)
671 olsr_select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)
673 return select(nfds, readfds, writefds, exceptfds, timeout);
677 check_wireless_interface(char *ifname)
681 memset(&ifr, 0, sizeof(ifr));
682 strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
684 return (ioctl(olsr_cnf->ioctl_s, SIOCGIWNAME, &ifr) >= 0) ? 1 : 0;
689 #include <linux/sockios.h>
690 #include <linux/types.h>
692 /* This data structure is used for all the MII ioctl's */
700 /* Basic Mode Control Register */
701 #define MII_BMCR 0x00
702 #define MII_BMCR_RESET 0x8000
703 #define MII_BMCR_LOOPBACK 0x4000
704 #define MII_BMCR_100MBIT 0x2000
705 #define MII_BMCR_AN_ENA 0x1000
706 #define MII_BMCR_ISOLATE 0x0400
707 #define MII_BMCR_RESTART 0x0200
708 #define MII_BMCR_DUPLEX 0x0100
709 #define MII_BMCR_COLTEST 0x0080
711 /* Basic Mode Status Register */
712 #define MII_BMSR 0x01
713 #define MII_BMSR_CAP_MASK 0xf800
714 #define MII_BMSR_100BASET4 0x8000
715 #define MII_BMSR_100BASETX_FD 0x4000
716 #define MII_BMSR_100BASETX_HD 0x2000
717 #define MII_BMSR_10BASET_FD 0x1000
718 #define MII_BMSR_10BASET_HD 0x0800
719 #define MII_BMSR_NO_PREAMBLE 0x0040
720 #define MII_BMSR_AN_COMPLETE 0x0020
721 #define MII_BMSR_REMOTE_FAULT 0x0010
722 #define MII_BMSR_AN_ABLE 0x0008
723 #define MII_BMSR_LINK_VALID 0x0004
724 #define MII_BMSR_JABBER 0x0002
725 #define MII_BMSR_EXT_CAP 0x0001
728 calculate_if_metric(char *ifname)
730 if (check_wireless_interface(ifname)) {
732 strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
735 if (ioctl(olsr_cnf->ioctl_s, SIOCGIWRATE, &ifr) < 0) {
736 OLSR_PRINTF(1, "Not able to find rate for WLAN interface %s\n", ifname);
737 return WEIGHT_WLAN_11MB;
740 OLSR_PRINTF(1, "Bitrate %d\n", ifr.ifr_ifru.ifru_ivalue);
742 //WEIGHT_WLAN_LOW, /* <11Mb WLAN */
743 //WEIGHT_WLAN_11MB, /* 11Mb 802.11b */
744 //WEIGHT_WLAN_54MB, /* 54Mb 802.11g */
745 return WEIGHT_WLAN_LOW;
750 struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
752 memset(&ifr, 0, sizeof(ifr));
753 strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
755 if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
757 OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n", ifr.ifr_name, strerror(errno));
758 return WEIGHT_ETHERNET_DEFAULT;
761 mii->reg_num = MII_BMCR;
762 if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIREG, &ifr) < 0) {
763 OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name, strerror(errno));
764 return WEIGHT_ETHERNET_DEFAULT;
768 OLSR_PRINTF(1, "%s: ", ifr.ifr_name);
769 OLSR_PRINTF(1, "%s Mbit, %s duplex\n", (bmcr & MII_BMCR_100MBIT) ? "100" : "10", (bmcr & MII_BMCR_DUPLEX) ? "full" : "half");
771 is_if_link_up(ifname);
773 if (mii->val_out & MII_BMCR_100MBIT)
774 return WEIGHT_ETHERNET_100MB;
776 return WEIGHT_ETHERNET_10MB;
777 //WEIGHT_ETHERNET_1GB, /* Ethernet 1Gb */
783 is_if_link_up(char *ifname)
785 if (check_wireless_interface(ifname)) {
786 /* No link checking on wireless devices */
791 struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
793 memset(&ifr, 0, sizeof(ifr));
794 strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
796 if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
798 OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n", ifr.ifr_name, strerror(errno));
799 return WEIGHT_ETHERNET_DEFAULT;
801 mii->reg_num = MII_BMSR;
802 if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIREG, &ifr) < 0) {
803 OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name, strerror(errno));
804 return WEIGHT_ETHERNET_DEFAULT;
808 OLSR_PRINTF(1, "%s: ", ifr.ifr_name);
809 OLSR_PRINTF(1, "%s\n", (bmsr & MII_BMSR_LINK_VALID) ? "link ok " : "no link ");
811 return (bmsr & MII_BMSR_LINK_VALID);
818 calculate_if_metric(char *ifname)
820 return check_wireless_interface(ifname);
824 bool olsr_if_isup(const char * dev)
828 memset(&ifr, 0, sizeof(ifr));
829 strscpy(ifr.ifr_name, dev, IFNAMSIZ);
831 if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
832 perror("ioctl SIOCGIFFLAGS (get flags)");
835 return (ifr.ifr_flags & IFF_UP) != 0;
838 int olsr_if_set_state(const char *dev, bool up) {
842 memset(&ifr, 0, sizeof(ifr));
843 strscpy(ifr.ifr_name, dev, IFNAMSIZ);
845 if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) {
846 perror("ioctl SIOCGIFFLAGS (get flags)");
850 oldflags = ifr.ifr_flags;
852 ifr.ifr_flags |= IFF_UP;
855 ifr.ifr_flags &= ~IFF_UP;
858 if (oldflags == ifr.ifr_flags) {
859 /* interface is already up/down */
863 if (ioctl(olsr_cnf->ioctl_s, SIOCSIFFLAGS, &ifr) < 0) {
864 perror("ioctl SIOCSIFFLAGS (set flags)");
871 int olsr_if_setip(const char *dev, union olsr_ip_addr *ip, int ip_version) {
875 /* first activate interface */
876 if (olsr_if_set_state(dev, true)) {
880 memset(&ifr, 0, sizeof(ifr));
881 strscpy(ifr.ifr_name, dev, IFNAMSIZ);
883 memset(&s, 0, sizeof(s));
884 s.sa_family = ip_version == 0 ? olsr_cnf->ip_version : ip_version;
885 if (s.sa_family == AF_INET) {
886 ((struct sockaddr_in *)&s)->sin_addr = ip->v4;
889 ((struct sockaddr_in6 *)&s)->sin6_addr = ip->v6;
891 memcpy(&ifr.ifr_addr, &s, sizeof(s));
893 if (ioctl(olsr_cnf->ioctl_s, SIOCSIFADDR, ifr) < 0) {
894 perror("ioctl SIOCSIFADDR (set addr)");
903 * indent-tabs-mode: nil