📄 net.c
字号:
if(bind_socket_to_device(sock, int_name) < 0) { fprintf(stderr, "Could not bind socket to device... exiting!\n\n"); syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n"); close(sock); return -1; } if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) { perror("bind"); syslog(LOG_ERR, "bind: %m"); close(sock); return -1; } /* *FIXME: One should probably fetch the flags first *using F_GETFL.... */ if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n"); return sock;}/** *Creates a nonblocking IPv6 socket *@param sin sockaddr_in6 struct. Used for bind(2). *@return the FD of the socket or -1 on error. */intgetsocket6(struct sockaddr_in6 *sin, int bufspace, char *int_name){ int sock, on = 1; if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { perror("socket"); syslog(LOG_ERR, "socket: %m"); return (-1); }#ifdef IPV6_V6ONLY if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { perror("setsockopt(IPV6_V6ONLY)"); syslog(LOG_ERR, "setsockopt(IPV6_V6ONLY): %m"); }#endif //#ifdef SO_BROADCAST /* if (setsockopt(sock, SOL_SOCKET, SO_MULTICAST, &on, sizeof (on)) < 0) { perror("setsockopt"); syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); close(sock); return (-1); } */ //#endif#ifdef SO_RCVBUF for (on = bufspace; ; on -= 1024) { if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof (on)) == 0) break; if (on <= 8*1024) { perror("setsockopt"); syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m"); break; } }#endif if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { perror("SO_REUSEADDR failed"); close(sock); return (-1); } /* * WHEN USING KERNEL 2.6 THIS MUST HAPPEN PRIOR TO THE PORT BINDING!!!! */ /* Bind to device */ if(bind_socket_to_device(sock, int_name) < 0) { fprintf(stderr, "Could not bind socket to device... exiting!\n\n"); syslog(LOG_ERR, "Could not bind socket to device... exiting!\n\n"); close(sock); return -1; } if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) { perror("bind"); syslog(LOG_ERR, "bind: %m"); close(sock); return (-1); } /* *One should probably fetch the flags first *using F_GETFL.... */ if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n"); return sock;}intjoin_mcast(struct interface *ifs, int sock){ /* See linux/in6.h */ struct ipv6_mreq mcastreq; COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr); mcastreq.ipv6mr_interface = ifs->if_index;#if !defined __FreeBSD__ && !defined __MacOSX__ && !defined __NetBSD__ OLSR_PRINTF(3, "Interface %s joining multicast %s...", ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr)); /* Send multicast */ if(setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mcastreq, sizeof(struct ipv6_mreq)) < 0) { perror("Join multicast"); return -1; }#else#warning implement IPV6_ADD_MEMBERSHIP#endif /* Old libc fix */#ifdef IPV6_JOIN_GROUP /* Join reciever group */ if(setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mcastreq, sizeof(struct ipv6_mreq)) < 0)#else /* Join reciever group */ if(setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mcastreq, sizeof(struct ipv6_mreq)) < 0)#endif { perror("Join multicast send"); return -1; } if(setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&mcastreq.ipv6mr_interface, sizeof(mcastreq.ipv6mr_interface)) < 0) { perror("Set multicast if"); return -1; } OLSR_PRINTF(3, "OK\n"); return 0;}/* *From net-tools lib/interface.c * */intget_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in){ char addr6[40], devname[IFNAMSIZ]; char addr6p[8][5]; int plen, scope, dad_status, if_idx; FILE *f; struct sockaddr_in6 tmp_sockaddr6; if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) { while (fscanf(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], addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, &dad_status, devname) != EOF) { if (!strcmp(devname, ifname)) { sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]); OLSR_PRINTF(5, "\tinet6 addr: %s\n", addr6); OLSR_PRINTF(5, "\tScope: %d\n", scope); if(scope == scope_in) { 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], addr6p[6], addr6p[7]); inet_pton(AF_INET6,addr6,&tmp_sockaddr6); memcpy(&saddr6->sin6_addr, &tmp_sockaddr6, sizeof(struct in6_addr)); fclose(f); return 1; } } } fclose(f); } return 0;}/** * Wrapper for sendto(2) */ssize_tolsr_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen){ return sendto(s, buf, len, flags, to, tolen);}/** * Wrapper for recvfrom(2) */ssize_t olsr_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen){ return recvfrom(s, buf, len, flags, from, fromlen);}/** * Wrapper for select(2) */intolsr_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout){ return select(nfds, readfds, writefds, exceptfds, timeout);}intcheck_wireless_interface(char * ifname){ struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); return (ioctl(olsr_cnf->ioctl_s, SIOCGIWNAME, &ifr) >= 0) ? 1 : 0;}#if 0#include <linux/sockios.h>#include <linux/types.h>/* This data structure is used for all the MII ioctl's */struct mii_data { __u16 phy_id; __u16 reg_num; __u16 val_in; __u16 val_out;};/* Basic Mode Control Register */#define MII_BMCR 0x00#define MII_BMCR_RESET 0x8000#define MII_BMCR_LOOPBACK 0x4000#define MII_BMCR_100MBIT 0x2000#define MII_BMCR_AN_ENA 0x1000#define MII_BMCR_ISOLATE 0x0400#define MII_BMCR_RESTART 0x0200#define MII_BMCR_DUPLEX 0x0100#define MII_BMCR_COLTEST 0x0080/* Basic Mode Status Register */#define MII_BMSR 0x01#define MII_BMSR_CAP_MASK 0xf800#define MII_BMSR_100BASET4 0x8000#define MII_BMSR_100BASETX_FD 0x4000#define MII_BMSR_100BASETX_HD 0x2000#define MII_BMSR_10BASET_FD 0x1000#define MII_BMSR_10BASET_HD 0x0800#define MII_BMSR_NO_PREAMBLE 0x0040#define MII_BMSR_AN_COMPLETE 0x0020#define MII_BMSR_REMOTE_FAULT 0x0010#define MII_BMSR_AN_ABLE 0x0008#define MII_BMSR_LINK_VALID 0x0004#define MII_BMSR_JABBER 0x0002#define MII_BMSR_EXT_CAP 0x0001intcalculate_if_metric(char *ifname){ if(check_wireless_interface(ifname)) { struct ifreq ifr; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); /* Get bit rate */ if(ioctl(olsr_cnf->ioctl_s, SIOCGIWRATE, &ifr) < 0) { OLSR_PRINTF(1, "Not able to find rate for WLAN interface %s\n", ifname); return WEIGHT_WLAN_11MB; } OLSR_PRINTF(1, "Bitrate %d\n", ifr.ifr_ifru.ifru_ivalue); //WEIGHT_WLAN_LOW, /* <11Mb WLAN */ //WEIGHT_WLAN_11MB, /* 11Mb 802.11b */ //WEIGHT_WLAN_54MB, /* 54Mb 802.11g */ return WEIGHT_WLAN_LOW; } else { /* Ethernet */ /* Mii wizardry */ struct ifreq ifr; struct mii_data *mii = (struct mii_data *)&ifr.ifr_data; int bmcr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIPHY, &ifr) < 0) { if (errno != ENODEV) OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n", ifr.ifr_name, strerror(errno)); return WEIGHT_ETHERNET_DEFAULT; } mii->reg_num = MII_BMCR; if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIREG, &ifr) < 0) { OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name, strerror(errno)); return WEIGHT_ETHERNET_DEFAULT; } bmcr = mii->val_out; OLSR_PRINTF(1, "%s: ", ifr.ifr_name); OLSR_PRINTF(1, "%s Mbit, %s duplex\n", (bmcr & MII_BMCR_100MBIT) ? "100" : "10", (bmcr & MII_BMCR_DUPLEX) ? "full" : "half"); is_if_link_up(ifname); if(mii->val_out & MII_BMCR_100MBIT) return WEIGHT_ETHERNET_100MB; else return WEIGHT_ETHERNET_10MB; //WEIGHT_ETHERNET_1GB, /* Ethernet 1Gb */ }}olsr_boolis_if_link_up(char *ifname){ if(check_wireless_interface(ifname)) { /* No link checking on wireless devices */ return OLSR_TRUE; } else { /* Mii wizardry */ struct ifreq ifr; struct mii_data *mii = (struct mii_data *)&ifr.ifr_data; int bmsr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIPHY, &ifr) < 0) { if (errno != ENODEV) OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n", ifr.ifr_name, strerror(errno)); return WEIGHT_ETHERNET_DEFAULT; } mii->reg_num = MII_BMSR; if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIREG, &ifr) < 0) { OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name, strerror(errno)); return WEIGHT_ETHERNET_DEFAULT; } bmsr = mii->val_out; OLSR_PRINTF(1, "%s: ", ifr.ifr_name); OLSR_PRINTF(1, "%s\n", (bmsr & MII_BMSR_LINK_VALID) ? "link ok " : "no link "); return (bmsr & MII_BMSR_LINK_VALID); }}#elseintcalculate_if_metric(char *ifname){ return check_wireless_interface(ifname);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -