/* * @(#) $Id: rsvp_socks.c,v 4.22 1998/03/18 19:46:20 lindell Exp $ */ /************************ rsvp_socks.h ******************************* * * * IPv4/IPv6 Sockets Interface based on RFC2133 and more * * * *********************************************************************/ /**************************************************************************** RSVPD -- ReSerVation Protocol Daemon USC Information Sciences Institute Marina del Rey, California Original Version: Shai Herzog, Nov. 1993. Current Version: Bob Lindell, July 1997. Copyright (c) 1997 by the University of Southern California All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation in source and binary forms for any purpose and without fee is hereby granted, provided that both the above copyright notice and this permission notice appear in all copies, and that any documentation, advertising materials, and other materials related to such distribution and use acknowledge that the software was developed in part by the University of Southern California, Information Sciences Institute. The name of the University may not be used to endorse or promote products derived from this software without specific prior written permission. THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about the suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Other copyrights might apply to parts of this software and are so noted when applicable. ********************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "rsvp_socks.h" #ifdef __FreeBSD__ #include #include #include #include #include #ifdef USE_IPV6 #include #endif /* USE_IPV6 */ #endif /* __FreeBSD__ */ #ifdef sun extern int gethostname(char *,int); #if (!defined(__SVR4) && !defined(__svr4__)) extern int ioctl(int,int,caddr_t); extern int socket(int,int,int); #endif /* (!defined(__SVR4) && !defined(__svr4__)) */ #endif /* sun */ #define PREFIX(x) prefix((char *) &(x),NBITS(x)) #ifdef USE_IPV6 #define _AF_INET AF_INET6 #ifdef sun #define IFREQ v6conf #define IF_ADDR v6cf_addr_in #define IF_NAME v6cf_name #define IFREQMASK v6maskreq #define IF_MASKNAME v6mr_name #define IF_MASKADDR v6mr_mask #define IFREQADDR v6addrreq #define IF_ADDRNAME v6ar_name #define IF_ADDRADDR v6ar_addr #define PREFIX6(x) x #define _SIOCGIFCONF SIOCGIFV6CONF #define _SIOCGIFADDR SIOCGIFV6ADDR #define SIOCGIFNETMASK6 SIOCGIFV6MASK #endif /* sun */ #else /* USE_IPV6 */ #define _AF_INET AF_INET #define IFREQ ifreq #define IF_ADDR ifr_addr #define IF_NAME ifr_name #define IFREQADDR IFREQ #define IF_ADDRNAME IF_NAME #define IF_ADDRADDR IF_ADDR #define _SIOCGIFCONF SIOCGIFCONF #define _SIOCGIFADDR SIOCGIFADDR #endif /* USE_IPV6 */ #ifndef __FreeBSD__ static int if_indextoprefix(unsigned int n); #endif /* __FreeBSD__ */ static int if_indextoflags(unsigned int n); static unsigned int prefix(unsigned char *p,unsigned int n); #ifdef sun const struct in_addr inaddr_any = {{{INADDR_ANY}}}; #else /* sun */ const struct in_addr inaddr_any = {INADDR_ANY}; #endif /* sun */ static struct if_nameindex ifs[MAX_INTERFACES]; static unsigned int maxindex = 0; static int once = TRUE; #ifdef __FreeBSD__ /* * Expand the compacted form of addresses as returned via the * configuration read via sysctl(). */ #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) /* * FreeBSD and other *BSD use sysctl to get the interface list. * This code was taken from ifconfig.8. The code was contributed * to rsvpd from Kenjiro Cho . */ static struct if_attributes ifap[MAX_INTERFACES][MAX_INTERFACES]; static struct sockaddr *prefixes[MAX_INTERFACES][MAX_INTERFACES]; struct if_nameindex * if_nameindex() { struct if_msghdr *ifm; struct ifa_msghdr *ifam; struct sockaddr *s; struct sockaddr_dl *sdl; char *buf, *lim, *next, *p, *cp; size_t needed; int mib[6], index, i, j; once = TRUE; for (i = 0; i < MAX_INTERFACES; i++) { for (j = 0; ifap[i][j].addr != NULL; j++) free(ifap[i][j].addr); ifap[i][0].addr = NULL; for (j = 0; prefixes[i][j] != 0; j++) free(prefixes[i][j]); prefixes[i][0] = NULL; if (ifs[i].if_name != NULL) if (strcmp(ifs[i].if_name,"") != 0) free(ifs[i].if_name); ifs[i].if_name = NULL; } mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; #ifdef USE_IPV6 mib[3] = 0; /* address family */ #else /* USE_IPV6 */ mib[3] = AF_INET; /* address family */ #endif /* USE_IPV6 */ mib[4] = NET_RT_IFLIST; mib[5] = 0; if (FAILED(sysctl(mib, 6, NULL, &needed, NULL, 0))) return(NULL); if ((buf = malloc(needed)) == NULL) return(NULL); if (FAILED(sysctl(mib, 6, buf, &needed, NULL, 0))) { free(buf); return(NULL); } lim = buf + needed; for (next = buf; next < lim; next += ifm->ifm_msglen) { ifm = (struct if_msghdr *)next; switch (ifm->ifm_type) { case RTM_IFINFO: index = ifm->ifm_index - 1; if (index < 0 || index >= MAX_INTERFACES) continue; ifs[index].if_index = index + 1; /* real ifm_index value */ #ifdef ALTQ /* * back out the hack; it doesn't work if there is a pad * for alignment. */ sdl = (struct sockaddr_dl *)(ifm + 1); #else /* * The size of a struct if_msghdr is different on an IPv4 * and IPv6 kernel. To achieve binary compatibility, we * find the struct sockaddr_dl by counting backwards from * the end of the message. */ /* sdl = (struct sockaddr_dl *)(ifm + 1); */ sdl = (struct sockaddr_dl *) ((char *)ifm + ifm->ifm_msglen - sizeof(struct sockaddr_dl)); #endif if ((ifs[index].if_name = malloc(sdl->sdl_nlen+1)) == NULL) break; strncpy(ifs[index].if_name, sdl->sdl_data, sdl->sdl_nlen); ifs[index].if_name[sdl->sdl_nlen] = '\0'; break; case RTM_NEWADDR: ifam = (struct ifa_msghdr *)ifm; index = ifam->ifam_index - 1; if (index < 0 || index >= MAX_INTERFACES) continue; p = (char *)(ifam + 1); for (i = 1; i < 0x100; i <<= 1) { if ((ifam->ifam_addrs & i) == 0) continue; if (i == RTA_IFA) { s = (struct sockaddr *)p; switch (s->sa_family) { case AF_INET: #ifdef USE_IPV6 case AF_INET6: #endif /* USE_IPV6 */ if ((cp = malloc(s->sa_len)) == NULL) break; memcpy(cp, s, s->sa_len); for (j = 0; ifap[index][j].addr != NULL; j++) ; ifap[index][j++].addr = (struct sockaddr *) cp; ifap[index][j].addr = NULL; break; default: break; } } if (i == RTA_NETMASK) { s = (struct sockaddr *)p; if ((cp = malloc(s->sa_len)) == NULL) break; memcpy(cp, s, s->sa_len); for (j = 0; prefixes[index][j] != 0; j++) ; prefixes[index][j] = (struct sockaddr * ) cp; } ADVANCE(p, (struct sockaddr *)p); } break; default: break; } } free(buf); /* * make sure there's no index gap, other routines use NULL-if_name * as an end mark. */ for (index = MAX_INTERFACES -1; index > 0; index--) if (ifs[index].if_name != NULL) break; maxindex = index + 1; for (; index > 0; index--) if (ifs[index].if_name == NULL) ifs[index].if_name = ""; once = FALSE; return(ifs); } #else /* __FreeBSD__ */ struct if_nameindex * if_nameindex() { int fd,n = 0; struct ifconf ifc; struct IFREQ *p,*last; static char buffer[MAX_INTERFACES * sizeof(struct IFREQ) + sizeof(struct ifconf)]; once = TRUE; fd = socket(_AF_INET,SOCK_DGRAM,PF_UNSPEC); if (FAILED(fd)) return(NULL); ifc.ifc_buf = buffer; ifc.ifc_len = sizeof(buffer); if (FAILED(ioctl(fd,_SIOCGIFCONF,(caddr_t) &ifc))) { close(fd); return(NULL); } close(fd); last = ((struct IFREQ *) ifc.ifc_req) + ifc.ifc_len; for (p = (struct IFREQ *) ifc.ifc_req;p < last; p++) { if (strncmp(p->IF_NAME,"",IFNAMSIZ) == 0) continue; ifs[n].if_name = p->IF_NAME; ifs[n].if_index = n + 1; n++; } ifs[n].if_index = 0; ifs[n].if_name = NULL; once = FALSE; maxindex = n; return(ifs); } #endif /* __FreeBSD__ */ void if_freenameindex(struct if_nameindex *p) { } unsigned int if_nametoindex(const char *ifname) { struct if_nameindex *p; if (once) if_freenameindex(if_nameindex()); for (p = ifs;p->if_name != NULL; p++) if (strncmp(ifname,p->if_name,IFNAMSIZ) == 0) return(p->if_index); return(0); } char * if_indextoname(unsigned int ifindex,char *ifname) { if (once) if_freenameindex(if_nameindex()); if ((ifindex < 1) || (ifindex > maxindex)) return(NULL); strncpy(ifname,ifs[ifindex - 1].if_name,IFNAMSIZ); return(ifname); } #ifndef __FreeBSD__ const char * inet_ntop(int af,const void *src,char *dst,size_t size) { switch (af) { case AF_INET: if (size < INET_ADDRSTRLEN) return(NULL); strncpy(dst,inet_ntoa(*(struct in_addr *) src), INET_ADDRSTRLEN); return(dst); #ifdef USE_IPV6 case AF_INET6: if (size < INET6_ADDRSTRLEN) return(NULL); strncpy(dst,addr2ascii(AF_INET6, (struct in6_addr *) src, sizeof(struct in6_addr),NULL), INET6_ADDRSTRLEN); return(dst); #endif /* USE_IPV6 */ default: return(NULL); } } int inet_pton(int af,const char *src,void *dst) { switch (af) { case AF_INET: ((struct in_addr *) dst)->s_addr = inet_addr(src); return((((struct in_addr *) dst)->s_addr == SYS_ERROR) ? FALSE : 1); #ifdef USE_IPV6 case AF_INET6: return((ascii2addr(AF_INET6,src,dst) == SYS_ERROR) ? FALSE : 1); #endif /* USE_IPV6 */ default: return(SYS_ERROR); } } struct hostent * gethostbyname2(const char *name,int af) { switch (af) { case AF_INET: return(gethostbyname(name)); #ifdef USE_IPV6 case AF_INET6: return(hostname2addr(name,AF_INET6)); #endif /* USE_IPV6 */ default: return(NULL); } return(NULL); } #endif /* __FreeBSD__ */ struct if_attributes * if_attributes(unsigned int n) { #ifdef __FreeBSD__ int i,flags; struct if_attributes *l; struct sockaddr *s; if (once) if_freenameindex(if_nameindex()); if ((n < 1) || (n > maxindex)) return(NULL); flags = if_indextoflags(n); l = ifap[--n]; i = 0; for(s = l->addr; s != NULL; s = (++l)->addr) { l->flags = flags; switch (s->sa_family) { case AF_INET: l->prefix = PREFIX(((struct sockaddr_in *) prefixes[n][i])->sin_addr.s_addr); break; #ifdef USE_IPV6 case AF_INET6: l->prefix = PREFIX(((struct sockaddr_in6 *) prefixes[n][i])->sin6_addr); break; #endif /* USE_IPV6 */ default: l->prefix = 0; break; } i++; } return(ifap[n]); #else /* __FreeBSD__ */ static struct if_attributes ret[2]; ret[0].addr = if_indextoaddr(n,AF_UNSPEC); ret[0].prefix = if_indextoprefix(n); ret[0].flags = if_indextoflags(n); ret[1].addr = NULL; #if (defined(sun) && defined(USE_IPV6)) if (ret[0].addr->sa_family == AF_INET6) { int fd; struct v6preinforeq ifr6; if (if_indextoname(n,ifr6.v6pr_name) == NULL) return(ret); fd = socket(_AF_INET,SOCK_DGRAM,PF_UNSPEC); if (FAILED(fd)) return(ret); if (FAILED(ioctl(fd,SIOCGIFV6PREINFO,(caddr_t) &ifr6))) { close(fd); return(ret); } close(fd); if (!(ifr6.v6pr_flags & LV6IF_ADDRESSED)) ret[0].addr = NULL; } #endif /* (defined(sun) && defined(USE_IPV6)) */ return(ret); #endif /* __FreeBSD__ */ } unsigned int if_addrtoindex(struct sockaddr *s) { struct if_nameindex *p,*q; struct if_attributes *l; struct sockaddr *s2; p = if_nameindex(); if (p == NULL) return(0); for (q = p;q->if_name != NULL; q++) { l = if_attributes(q->if_index); for(s2 = l->addr; s2 != NULL; s2 = (++l)->addr) if (net_sockaddr_equal(s,s2)) { if_freenameindex(p); return(q->if_index); } } if_freenameindex(p); return(0); } struct sockaddr * if_indextoaddr(unsigned int index,int af) { #ifdef __FreeBSD__ struct sockaddr *s; struct if_attributes *l; l = if_attributes(index); /* FIX: choose BEST address ? */ for(s = l->addr; s != NULL; s = (++l)->addr) if ((af == AF_UNSPEC) || (af == s->sa_family)) return(s); return(NULL); #else /* __FreeBSD__ */ int fd; static struct ifreq ifr; #ifdef USE_IPV6 static struct IFREQADDR ifr6; static struct sockaddr_in6 sin; if (if_indextoname(index,ifr6.IF_ADDRNAME) == NULL) return(NULL); fd = socket(_AF_INET,SOCK_DGRAM,PF_UNSPEC); if (FAILED(fd)) return(NULL); if (FAILED(ioctl(fd,_SIOCGIFADDR,(caddr_t) &ifr6))) { close(fd); return(NULL); } close(fd); if (!IN6_ARE_ADDR_EQUAL(&ifr6.IF_ADDRADDR,&in6addr_any)) { if ((af != AF_UNSPEC) && (af != AF_INET6)) return(NULL); NET_SOCKADDR_IPv6(&sin,ifr6.IF_ADDRADDR); return((struct sockaddr *) &sin); } #endif /* USE_IPV6 */ if (if_indextoname(index,ifr.ifr_name) == NULL) return(NULL); fd = socket(AF_INET,SOCK_DGRAM,PF_UNSPEC); if (FAILED(fd)) return(NULL); if (FAILED(ioctl(fd,SIOCGIFADDR,(caddr_t) &ifr))) { close(fd); return(NULL); } close(fd); if ((af != AF_UNSPEC) && (af != AF_INET)) return(NULL); return((struct sockaddr *) &ifr.ifr_addr); #endif /* __FreeBSD__ */ } #ifndef __FreeBSD__ static int if_indextoprefix(unsigned int n) { int fd,ret = 0; struct sockaddr *s; struct ifreq ifr; #ifdef USE_IPV6 struct IFREQMASK ifr6; #endif /* USE_IPV6 */ s = if_indextoaddr(n,AF_UNSPEC); if (s == NULL) return(ret); fd = socket(_AF_INET,SOCK_DGRAM,PF_UNSPEC); if (FAILED(fd)) return(ret); switch (s->sa_family) { case AF_INET: if_indextoname(n,ifr.ifr_name); if (FAILED(ioctl(fd,SIOCGIFNETMASK,(caddr_t) &ifr))) break; ret = PREFIX(((struct sockaddr_in *) &ifr.ifr_addr) ->sin_addr.s_addr); break; #ifdef USE_IPV6 case AF_INET6: if_indextoname(n,ifr6.IF_MASKNAME); if (FAILED(ioctl(fd,SIOCGIFNETMASK6,(caddr_t) &ifr6))) break; ret = PREFIX6(ifr6.IF_MASKADDR); break; #endif /* USE_IPV6 */ default: break; } close(fd); return(ret); } #endif /* __FreeBSD__ */ static int if_indextoflags(unsigned int n) { int fd,ret = 0; struct ifreq ifr; fd = socket(_AF_INET,SOCK_DGRAM,PF_UNSPEC); if (FAILED(fd)) return(ret); if_indextoname(n,ifr.ifr_name); if (!FAILED(ioctl(fd,SIOCGIFFLAGS,(caddr_t) &ifr))) ret = ifr.ifr_flags; close(fd); return(ret); } static unsigned int prefix(unsigned char *p,unsigned int n) { unsigned int i,sum = 0; for (i = 0;i < n; i++) if (BSET_ISSET(i,p)) sum++; return(sum); } const char * net_inaddr_print(const char *s,int af) { static char buffer[MAX_ADDRSTRLEN]; switch (af) { case AF_INET: return(inet_ntop(AF_INET, (struct in_addr *) s, buffer,sizeof(buffer))); #ifdef USE_IPV6 case AF_INET6: return(inet_ntop(AF_INET6, (struct in6_addr *) s, buffer,sizeof(buffer))); #endif /* USE_IPV6 */ default: return(NULL); } } const char * net_inaddr_host(const char *s,int af) { struct hostent *hp; switch (af) { case AF_INET: hp = gethostbyaddr(s,sizeof(struct in_addr),AF_INET); if (hp == NULL) return(net_inaddr_print(s,af)); return(hp->h_name); #ifdef USE_IPV6 case AF_INET6: hp = gethostbyaddr(s,sizeof(struct in6_addr),AF_INET6); if (hp == NULL) return(net_inaddr_print(s,af)); return(hp->h_name); #endif /* USE_IPV6 */ default: return(NULL); } } int net_sockaddr_equal(const struct sockaddr *x,const struct sockaddr *y) { if (x->sa_family != y->sa_family) return(FALSE); switch (x->sa_family) { case AF_INET: if (!IN_ARE_ADDR_EQUAL( &((struct sockaddr_in *) x)->sin_addr, &((struct sockaddr_in *) y)->sin_addr)) return(FALSE); return(((struct sockaddr_in *) x)->sin_port == ((struct sockaddr_in *) y)->sin_port); #ifdef USE_IPV6 case AF_INET6: if (!IN6_ARE_ADDR_EQUAL( &((struct sockaddr_in6 *) x)->sin6_addr, &((struct sockaddr_in6 *) y)->sin6_addr)) return(FALSE); return(((struct sockaddr_in6 *) x)->sin6_port == ((struct sockaddr_in6 *) y)->sin6_port); #endif /* USE_IPV6 */ default: return(FALSE); } } const char * net_sockaddr_print(const struct sockaddr *s) { static char buffer[MAX_ADDRPORTSTRLEN],buffer2[MAX_ADDRSTRLEN]; switch (s->sa_family) { case AF_INET: sprintf(buffer,"%s/%hu",inet_ntop(AF_INET, &((struct sockaddr_in *) s)->sin_addr, buffer2,sizeof(buffer2)), ntohs(((struct sockaddr_in *) s)->sin_port)); return(buffer); #ifdef USE_IPV6 case AF_INET6: sprintf(buffer,"%s/%hu",inet_ntop(AF_INET6, &((struct sockaddr_in6 *) s)->sin6_addr, buffer2,sizeof(buffer2)), ntohs(((struct sockaddr_in6 *) s)->sin6_port)); return(buffer); #endif /* USE_IPV6 */ default: return(NULL); } } int net_addr_equal(const net_addr *x,const net_addr *y) { if (NET_UNEQUAL_TYPE(x,y)) return(FALSE); switch (NET_GET_TYPE(x)) { case NET_ADDR_IPv4: return(IN_ARE_ADDR_EQUAL(&NET_GET_ADDR_IPv4(x), &NET_GET_ADDR_IPv4(y))); case NET_ADDR_UDP_IPv4: return(memcmp(&NET_GET_ADDR_UDP_IPv4(x), &NET_GET_ADDR_UDP_IPv4(y), sizeof(NET_GET_ADDR_UDP_IPv4(x))) == 0); #ifdef USE_IPV6 case NET_ADDR_IPv6: return(IN6_ARE_ADDR_EQUAL(&NET_GET_ADDR_IPv6(x), &NET_GET_ADDR_IPv6(y))); case NET_ADDR_UDP_IPv6: return(memcmp(&NET_GET_ADDR_UDP_IPv6(x), &NET_GET_ADDR_UDP_IPv6(y), sizeof(NET_GET_ADDR_UDP_IPv6(x))) == 0); #endif /* USE_IPV6 */ default: return(FALSE); } } net_addr * net_addr_ip(net_addr *addr) { static net_addr addr2; switch (NET_GET_TYPE(addr)) { case NET_ADDR_UDP_IPv4: NET_SET_ADDR_IPv4(&addr2, NET_GET_ADDR_UDP_IPv4(addr).sin_addr); return(&addr2); #ifdef USE_IPV6 case NET_ADDR_UDP_IPv6: NET_SET_ADDR_IPv6(&addr2, NET_GET_ADDR_UDP_IPv6(addr).sin6_addr); return(&addr2); #endif /* USE_IPV6 */ default: addr2 = *addr; return(&addr2); } } int net_addr_assign(net_addr *addr,const struct sockaddr *s) { switch (s->sa_family) { case AF_INET: NET_SET_ADDR_IPv4(addr, ((struct sockaddr_in *) s)->sin_addr); return(TRUE); #ifdef USE_IPV6 case AF_INET6: NET_SET_ADDR_IPv6(addr, ((struct sockaddr_in6 *) s)->sin6_addr); return(TRUE); #endif /* USE_IPV6 */ default: return(FALSE); } } int net_addr_assign_udp(net_addr *addr,const struct sockaddr *s) { switch (s->sa_family) { case AF_INET: NET_SET_ADDR_UDP_IPv4(addr,*(struct sockaddr_in *) s); return(TRUE); #ifdef USE_IPV6 case AF_INET6: NET_SET_ADDR_UDP_IPv6(addr,*(struct sockaddr_in6 *) s); return(TRUE); #endif /* USE_IPV6 */ default: return(FALSE); } } int net_addr_ascii(net_addr *addr,const char *str) { struct hostent *hp; struct in_addr in; #ifdef USE_IPV6 struct in6_addr in6; #endif /* USE_IPV6 */ if (inet_pton(AF_INET,str,&in) == 1) { NET_SET_ADDR_IPv4(addr,in); return(TRUE); } hp = gethostbyname2(str,AF_INET); if (hp != NULL) { memcpy(&in,hp->h_addr,hp->h_length); NET_SET_ADDR_IPv4(addr,in); return(TRUE); } #ifdef USE_IPV6 if (inet_pton(AF_INET6,str,&in6) == 1) { NET_SET_ADDR_IPv6(addr,in6); return(TRUE); } hp = gethostbyname2(str,AF_INET6); if (hp != NULL) { memcpy(&in6,hp->h_addr,hp->h_length); NET_SET_ADDR_IPv6(addr,in6); return(TRUE); } #endif /* USE_IPV6 */ return(FALSE); } const char * net_addr_print(const net_addr *addr) { static char buffer[MAX_ADDRPORTSTRLEN],buffer2[MAX_ADDRSTRLEN]; switch(NET_GET_TYPE(addr)) { case NET_ADDR_IPv4: return(inet_ntop(AF_INET,&NET_GET_ADDR_IPv4(addr), buffer,sizeof(buffer))); case NET_ADDR_UDP_IPv4: sprintf(buffer,"%s/%hu",inet_ntop(AF_INET, &NET_GET_ADDR_UDP_IPv4(addr).sin_addr, buffer2,sizeof(buffer2)), ntohs(NET_GET_ADDR_UDP_IPv4(addr).sin_port)); return(buffer); #ifdef USE_IPV6 case NET_ADDR_IPv6: return(inet_ntop(AF_INET6,&NET_GET_ADDR_IPv6(addr), buffer,sizeof(buffer))); case NET_ADDR_UDP_IPv6: sprintf(buffer,"%s/%hu",inet_ntop(AF_INET6, &NET_GET_ADDR_UDP_IPv6(addr).sin6_addr, buffer2,sizeof(buffer2)), ntohs(NET_GET_ADDR_UDP_IPv6(addr).sin6_port)); return(buffer); #endif /* USE_IPV6 */ default: return(NULL); } } const char * net_addr_host(const net_addr *addr) { static char buffer[MAX_HOSTPORTSTRLEN]; struct hostent *hp; switch(NET_GET_TYPE(addr)) { case NET_ADDR_IPv4: hp = gethostbyaddr((char *) &NET_GET_ADDR_IPv4(addr), sizeof(NET_GET_ADDR_IPv4(addr)),AF_INET); if (hp == NULL) return(net_addr_print(addr)); return(hp->h_name); case NET_ADDR_UDP_IPv4: hp = gethostbyaddr( (char *) &NET_GET_ADDR_UDP_IPv4(addr).sin_addr, sizeof(NET_GET_ADDR_UDP_IPv4(addr).sin_addr), AF_INET); if (hp == NULL) return(net_addr_print(addr)); sprintf(buffer,"%s/%hu",hp->h_name, ntohs(NET_GET_ADDR_UDP_IPv4(addr).sin_port)); return(buffer); #ifdef USE_IPV6 case NET_ADDR_IPv6: hp = gethostbyaddr((char *) &NET_GET_ADDR_IPv6(addr), sizeof(NET_GET_ADDR_IPv6(addr)),AF_INET6); if (hp == NULL) return(net_addr_print(addr)); return(hp->h_name); case NET_ADDR_UDP_IPv6: hp = gethostbyaddr( (char *) &NET_GET_ADDR_UDP_IPv6(addr).sin6_addr, sizeof(NET_GET_ADDR_UDP_IPv6(addr).sin6_addr), AF_INET6); if (hp == NULL) return(net_addr_print(addr)); sprintf(buffer,"%s/%hu",hp->h_name, ntohs(NET_GET_ADDR_UDP_IPv6(addr).sin6_port)); return(buffer); #endif /* USE_IPV6 */ default: return(NULL); } } int net_if_equal(const net_if *x,const net_if *y) { if (NET_UNEQUAL_TYPE(x,y)) return(FALSE); switch (NET_GET_TYPE(x)) { case NET_IF_UNKNOWN: return(TRUE); case NET_IF_ID: return(NET_GET_IF_ID(x) == NET_GET_IF_ID(y)); case NET_IF_STRING: return(strcmp(NET_GET_IF_STRING(x), NET_GET_IF_STRING(y)) == 0); case NET_IF_PHY: return((NET_GET_IF_PHY_ID(x) == NET_GET_IF_PHY_ID(y)) && net_addr_equal(&NET_GET_IF_PHY_ADDR(x), &NET_GET_IF_PHY_ADDR(y))); case NET_IF_VIF: return((NET_GET_IF_VIF_ID(x) == NET_GET_IF_VIF_ID(y)) && net_addr_equal(&NET_GET_IF_VIF_ADDR(x), &NET_GET_IF_VIF_ADDR(y))); default: return(FALSE); } } const char * net_if_print(const net_if *inf) { static char buffer[MAX_ADDRSTRLEN]; switch(NET_GET_TYPE(inf)) { case NET_IF_UNKNOWN: return("unknown"); case NET_IF_ID: sprintf(buffer,"%d",NET_GET_IF_ID(inf)); return(buffer); case NET_IF_STRING: return(NET_GET_IF_STRING(inf)); case NET_IF_PHY: return(net_addr_print(&NET_GET_IF_PHY_ADDR(inf))); case NET_IF_VIF: sprintf(buffer,"%s vif %d", net_addr_print(&NET_GET_IF_VIF_ADDR(inf)), NET_GET_IF_VIF_ID(inf)); return(buffer); default: return(NULL); } } net_addr * net_get_default_interface() { char name[MAXHOSTNAMELEN]; static net_addr addr; if (FAILED(gethostname(name,MAXHOSTNAMELEN))) return(NULL); if (!net_addr_ascii(&addr,name)) return(NULL); return(&addr); }