📄 net.c
字号:
perror("SO_REUSEADDR failed"); close(sock); return (-1); } if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) { perror("SO_REUSEPORT failed"); return (-1); }#ifdef IPV6_RECVPKTINFO if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) { perror("IPV6_RECVPKTINFO failed"); return (-1); }#elif defined IPV6_PKTINFO if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) < 0) { perror("IPV6_PKTINFO failed"); return (-1); }#endif if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) { perror("bind"); syslog(LOG_ERR, "bind: %m"); close(sock); return (-1); } 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 netinet6/in6.h */ struct ipv6_mreq mcastreq; COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr); mcastreq.ipv6mr_interface = ifs->if_index; OLSR_PRINTF(3, "Interface %s joining multicast %s...", ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr)); /* rfc 3493 */#ifdef IPV6_JOIN_GROUP /* Join reciever group */ if(setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mcastreq, sizeof(struct ipv6_mreq)) < 0)#else /* rfc 2133, obsoleted */ /* Join receiver 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;}int get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in){ struct ifaddrs *ifap, *ifa; const struct sockaddr_in6 *sin6 = NULL; struct in6_ifreq ifr6; int found = 0; int s6; u_int32_t flags6; if (getifaddrs(&ifap) != 0) { OLSR_PRINTF(3, "get_ipv6_address: getifaddrs() failed.\n"); return 0; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family == AF_INET6 && strcmp(ifa->ifa_name, ifname) == 0) { sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) continue; strncpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { OLSR_PRINTF(3, "socket(AF_INET6,SOCK_DGRAM)"); break; } ifr6.ifr_addr = *sin6; if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) { OLSR_PRINTF(3, "ioctl(SIOCGIFAFLAG_IN6)"); close(s6); break; } close(s6); flags6 = ifr6.ifr_ifru.ifru_flags6; if ((flags6 & IN6_IFF_ANYCAST) != 0) continue; if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { if (scope_in) { memcpy(&saddr6->sin6_addr, &sin6->sin6_addr, sizeof(struct in6_addr)); found = 1; break; } } else { if (scope_in == 0) { memcpy(&saddr6->sin6_addr, &sin6->sin6_addr, sizeof(struct in6_addr)); found = 1; break; } } } } freeifaddrs(ifap); if (found) return 1; return 0;}/** * Wrapper for sendto(2) */#ifdef SPOOFstatic u_int16_t ip_id = 0;#endif /* SPOOF */ssize_tolsr_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen){#ifdef SPOOF /* IPv4 for now! */ libnet_t *context; char errbuf[LIBNET_ERRBUF_SIZE]; libnet_ptag_t udp_tag, ip_tag, ether_tag; unsigned char enet_broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; int status; struct sockaddr_in *to_in = (struct sockaddr_in *) to; u_int32_t destip; struct interface *iface; udp_tag = ip_tag = ether_tag = 0; destip = to_in->sin_addr.s_addr; iface = if_ifwithsock (s); /* initialize libnet */ context = libnet_init(LIBNET_LINK, iface->int_name, errbuf); if (context == NULL) { OLSR_PRINTF (1, "libnet init: %s\n", libnet_geterror (context)); return (0); } /* initialize IP ID field if necessary */ if (ip_id == 0) { ip_id = (u_int16_t) (arc4random () & 0xffff); } udp_tag = libnet_build_udp (698, /* src port */ 698, /* dest port */ LIBNET_UDP_H + len, /* length */ 0, /* checksum */ buf, /* payload */ len, /* payload size */ context, /* context */ udp_tag); /* pblock */ if (udp_tag == -1) { OLSR_PRINTF (1, "libnet UDP header: %s\n", libnet_geterror (context)); return (0); } ip_tag = libnet_build_ipv4 (LIBNET_IPV4_H + LIBNET_UDP_H + len, /* len */ 0, /* TOS */ ip_id++, /* IP id */ 0, /* IP frag */ 1, /* IP TTL */ IPPROTO_UDP, /* protocol */ 0, /* checksum */ libnet_get_ipaddr4 (context), /* src IP */ destip, /* dest IP */ NULL, /* payload */ 0, /* payload len */ context, /* context */ ip_tag); /* pblock */ if (ip_tag == -1) { OLSR_PRINTF (1, "libnet IP header: %s\n", libnet_geterror (context)); return (0); } ether_tag = libnet_build_ethernet (enet_broadcast, /* ethernet dest */ libnet_get_hwaddr (context), /* ethernet source */ ETHERTYPE_IP, /* protocol type */ NULL, /* payload */ 0, /* payload size */ context, /* libnet handle */ ether_tag); /* pblock tag */ if (ether_tag == -1) { OLSR_PRINTF (1, "libnet ethernet header: %s\n", libnet_geterror (context)); return (0); } status = libnet_write (context); if (status == -1) { OLSR_PRINTF (1, "libnet packet write: %s\n", libnet_geterror (context)); return (0); } libnet_destroy (context); return (len);#else return sendto(s, buf, len, flags, to, tolen);#endif}/** * Wrapper for recvfrom(2) */ssize_t olsr_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen){ struct msghdr mhdr; struct iovec iov; union { struct cmsghdr cmsg; unsigned char chdr[4096]; } cmu; struct cmsghdr *cm; struct sockaddr_dl *sdl; struct sockaddr_in *sin = (struct sockaddr_in *) from; //XXX struct sockaddr_in6 *sin6; struct in6_addr *iaddr6; struct in6_pktinfo *pkti; struct interface *ifc; char addrstr[INET6_ADDRSTRLEN]; char iname[IFNAMSIZ]; int count; memset(&mhdr, 0, sizeof(mhdr)); memset(&iov, 0, sizeof(iov)); mhdr.msg_name = (caddr_t) from; mhdr.msg_namelen = *fromlen; mhdr.msg_iov = &iov; mhdr.msg_iovlen = 1; mhdr.msg_control = (caddr_t) &cmu; mhdr.msg_controllen = sizeof (cmu); iov.iov_len = len; iov.iov_base = buf; count = recvmsg (s, &mhdr, MSG_DONTWAIT); if (count <= 0) { return (count); } /* this needs to get communicated back to caller */ *fromlen = mhdr.msg_namelen; if (olsr_cnf->ip_version == AF_INET6) { for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&mhdr); cm; cm = (struct cmsghdr *)CMSG_NXTHDR(&mhdr, cm)) { if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO) { pkti = (struct in6_pktinfo *) CMSG_DATA(cm); iaddr6 = &pkti->ipi6_addr; if_indextoname(pkti->ipi6_ifindex, iname); } } } else { cm = &cmu.cmsg; sdl = (struct sockaddr_dl *) CMSG_DATA (cm); memset (iname, 0, sizeof (iname)); memcpy (iname, sdl->sdl_data, sdl->sdl_nlen); } ifc = if_ifwithsock (s); sin6 = (struct sockaddr_in6 *)from; OLSR_PRINTF (4, "%d bytes from %s, socket associated %s really received on %s\n", count, (olsr_cnf->ip_version == AF_INET6) ? inet_ntop(AF_INET6, (char *)&sin6->sin6_addr, addrstr, INET6_ADDRSTRLEN): inet_ntoa (sin->sin_addr), ifc->int_name, iname); if (strcmp (ifc->int_name, iname) != 0) { return (0); } return (count);}/** * 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);}int check_wireless_interface(char *ifname){#if defined __FreeBSD__ && !defined FBSD_NO_80211/* From FreeBSD ifconfig/ifieee80211.c ieee80211_status() */ struct ieee80211req ireq; u_int8_t data[32]; memset(&ireq, 0, sizeof(ireq)); strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name)); ireq.i_data = &data; ireq.i_type = IEEE80211_IOC_SSID; ireq.i_val = -1; return (ioctl(olsr_cnf->ioctl_s, SIOCG80211, &ireq) >= 0) ? 1 : 0;#else return 0;#endif}#include <sys/sockio.h>intcalculate_if_metric(char *ifname){ if(check_wireless_interface(ifname)) { /* Wireless */ return 1; } else { /* Ethernet */#if 0 /* Andreas: Perhaps SIOCGIFMEDIA is the way to do this? */ struct ifmediareq ifm; memset(&ifm, 0, sizeof(ifm)); strlcpy(ifm.ifm_name, ifname, sizeof(ifm.ifm_name)); if(ioctl(olsr_cnf->ioctl_s, SIOCGIFMEDIA, &ifm) < 0) { OLSR_PRINTF(1, "Error SIOCGIFMEDIA(%s)\n", ifm.ifm_name); return WEIGHT_ETHERNET_DEFAULT; } OLSR_PRINTF(1, "%s: STATUS 0x%08x\n", ifm.ifm_name, ifm.ifm_status);#endif return WEIGHT_ETHERNET_DEFAULT; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -