?? unp.c
字號:
/* * unp.c -- Unix Network Programming interface. * Created: Xie Han, net lab of Peking University. <e@pku.edu.cn> * * Function "in_chksum" is taken from the book: UNP volume 1. Special * thanks to Richard Stevens. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <errno.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/un.h>#include <net/if.h>#include <netinet/in.h>#include <netdb.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include "unp.h"unsigned short in_cksum(unsigned short *addr, int len){ int nleft = len; int sum = 0; unsigned short *w = addr; unsigned short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* 4mop up an odd byte, if necessary */ if (nleft == 1) { *(unsigned char *)(&answer) = *(unsigned char *)w ; sum += answer; } /* 4add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer);}inline static int __sockfd_to_family(int sockfd){ union { struct sockaddr_un sun; struct sockaddr sockaddr; } un; socklen_t addrlen = sizeof un; return getsockname(sockfd, &un.sockaddr, &addrlen) >= 0 ? un.sockaddr.sa_family : -1;}int mcast_join(int sockfd, const struct sockaddr *sockaddr,socklen_t addrlen, unsigned int ifindex, const char *ifname){ switch (sockaddr->sa_family) { case AF_INET: { struct ip_mreq mreq; struct ifreq ifreq; memcpy(&mreq.imr_multiaddr, &((struct sockaddr_in *)sockaddr)-> sin_addr, sizeof (struct in_addr)); if (ifindex > 0 || ifname) { if (ifindex > 0) { if (!if_indextoname(ifindex, ifreq.ifr_name)) { errno = ENXIO; break; } } else strncpy(ifreq.ifr_name, ifname, IFNAMSIZ); if (ioctl(sockfd, SIOCGIFADDR, &ifreq) >= 0) { memcpy(&mreq.imr_interface, &((struct sockaddr_in *)&ifreq. ifr_addr)->sin_addr, sizeof (struct in_addr)); } else break; } else mreq.imr_interface.s_addr = htonl(INADDR_ANY); return setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (struct ip_mreq)); }#ifdef IPV6 case AF_INET6: { struct ipv6_mreq mreq6; memcpy(&mreq6.ipv6mr_multiaddr, &((struct sockaddr_in6 *) sockaddr)->sin6_addr, sizeof (struct in6_addr)); if (ifindex > 0) mreq6.ipv6mr_interface = ifindex; else if (ifname) { if ((mreq6.ipv6mr_interface = if_nametoindex(ifname)) == 0) { errno = ENXIO; break; } } else mreq6.ipv6mr_interface = 0; return setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof (struct ipv6_mreq)); }#endif default: errno = EAFNOSUPPORT; break; } return -1;}int mcast_setif(int sockfd, unsigned int ifindex, const char *ifname){ switch (__sockfd_to_family(sockfd)) { case AF_INET: { struct ifreq ifreq; if (ifindex > 0 || ifname) { if (ifindex > 0) { if (!if_indextoname(ifindex, ifreq.ifr_name)) { errno = ENXIO; break; } } else strncpy(ifreq.ifr_name, ifname, IFNAMSIZ); if (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0) break; } else { ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr = htonl(INADDR_ANY); } return setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &((struct sockaddr_in *)&ifreq.ifr_addr)-> sin_addr, sizeof (struct in_addr)); }#ifdef IPV6 case AF_INET6: { if (ifindex == 0 && ifname) { if ((ifindex = if_nametoindex(ifname)) == 0) { errno = ENXIO; break; } } return setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof (unsigned int)); }#endif default: errno = EAFNOSUPPORT; break; } return -1;}int mcast_setloop(int sockfd, int loop){ switch (__sockfd_to_family(sockfd)) { case AF_INET: { unsigned char flag = loop; return setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &flag, sizeof (unsigned char)); }#ifdef IPV6 case AF_INET6: { unsigned int flag = loop; return setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &flag, sizeof (unsigned int)); }#endif default: errno = EAFNOSUPPORT; return -1; }}inline static int __getifaddr_ipv4(int ifindex, const char *ifname, struct in_addr *ifaddr){ struct ifreq ifreq; int sockfd; int ret = -1; char ifn[IFNAMSIZ]; if (ifindex > 0) { if (!(ifname = if_indextoname(ifindex, ifn))) { errno = ENXIO; return -1; } } if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { strncpy(ifreq.ifr_name, ifname, IFNAMSIZ); if ((ret = ioctl(sockfd, SIOCGIFADDR, &ifreq)) >= 0) *ifaddr = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; close(sockfd); } return ret;}#ifdef IPV6#define PROC_IFINET6_PATH "/proc/net/if_inet6"inline static int __getifaddr_ipv6(unsigned int ifindex, const char *ifname, struct in6_addr *ifaddr){ FILE *fp = fopen(PROC_IFINET6_PATH, "r"); char addrstr[INET6_ADDRSTRLEN]; char seg[8][5]; int index, plen, scope, flags; char ifn[IFNAMSIZ]; int ret = -1; if (fp) { while (fscanf(fp, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %s\n", seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6], seg[7], &index, &plen, &scope, &flags, ifn) != EOF) { if (ifindex == index || ifindex == 0 && strcmp(ifn, ifname) == 0) { sprintf(addrstr, "%s:%s:%s:%s:%s:%s:%s:%s", seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6], seg[7]); ret = inet_pton(AF_INET6, addrstr, ifaddr); goto out; } } errno = ENXIO;out: fclose(fp); } return ret;}#endifint getifaddr(int family, unsigned int ifindex, const char *ifname, void *ifaddr){ switch (family) { case AF_INET: return __getifaddr_ipv4(ifindex, ifname, (struct in_addr *)ifaddr);#ifdef IPV6 case AF_INET6: return __getifaddr_ipv6(ifindex, ifname, (struct in6_addr *)ifaddr);#endif default: errno = EAFNOSUPPORT; break; } return -1;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -