📄 rsvp_socks.c
字号:
/* * @(#) $Id: rsvp_socks.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing 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) 1999 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 <sys/param.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <arpa/inet.h>#include <net/if.h>#include <sys/ioctl.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#ifdef linux#include <linux/sockios.h>#include <linux/types.h>#include <linux/rtnetlink.h>#include <sys/uio.h>#include <errno.h>#include "libnetlink.h"#else /* linux */#include <sys/sockio.h>#endif /* linux */#include "rsvp_socks.h"#ifdef __FreeBSD__#include <sys/sysctl.h>#include <net/if_dl.h>#include <net/route.h>#ifdef USE_IPV6#ifdef IPV6_INRIA_VERSION#include <netinet/in6_var.h>#endif#endif /* USE_IPV6 */#endif /* __FreeBSD__ */#ifdef sunextern 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 unsigned int if_indextoflags(unsigned int n);static unsigned int if_indextomtu(unsigned int n);#ifndef linuxstatic unsigned int prefix(unsigned char *p,unsigned int n);#endif /* linux */#ifdef sunconst struct in_addr inaddr_any = {{{INADDR_ANY}}};#else /* sun */const struct in_addr inaddr_any = {INADDR_ANY};#endif /* sun */#if (defined(__FreeBSD__) || defined(sun))static struct if_nameindex ifs[MAX_INTERFACES];#endif /* (defined(__FreeBSD__) || defined(sun)) */#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 <kjc@csl.sony.co.jp>. */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; for (i = 0; i < MAX_INTERFACES; i++) { for (j = 0; ifap[i][j].addr != NULL; j++) { free(ifap[i][j].addr); ifap[i][j].addr = NULL; } for (j = 0; prefixes[i][j] != 0; j++) { free(prefixes[i][j]); prefixes[i][j] = 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 */ sdl = (struct sockaddr_dl *)(ifm + 1); 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; for (; index > 0; index--) if (ifs[index].if_name == NULL) ifs[index].if_name = ""; return(ifs);}#else /* __FreeBSD__ */#ifdef linux/* * The code was borrowed from the linux port of rsvpd done by Alexey * Kuznetsov <kuznet@ms2.inr.ac.ru> */static struct if_attributes ifap[MAX_INTERFACES];int store_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg){ int i; struct ifaddrmsg *ifa = NLMSG_DATA(n); struct rtattr *rta = IFA_RTA(ifa); int len = n->nlmsg_len; struct rtattr * rta_tb[IFA_MAX+1]; struct in_addr in;#ifdef USE_IPV6 struct in6_addr in6;#endif /* USE_IPV6 */ if (n->nlmsg_type != RTM_NEWADDR) return 0; len -= NLMSG_LENGTH(sizeof(*ifa)); if (len < 0) { errno = 0; return -1; } if (ifa->ifa_flags&IFA_F_TENTATIVE) return 0; parse_rtattr(rta_tb, IFA_MAX, rta, len); i = ifa->ifa_index; if (i >= MAX_INTERFACES) return 0; ifap[i].prefix = ifa->ifa_prefixlen; switch (ifa->ifa_family) { case AF_INET: memcpy(&in,RTA_DATA(rta_tb[IFA_ADDRESS]), sizeof(in)); ifap[i].addr = malloc(sizeof(struct sockaddr_in)); NET_SOCKADDR_IPv4((struct sockaddr_in *) ifap[i].addr,in); break;#ifdef USE_IPV6 case AF_INET6: memcpy(&in6,RTA_DATA(rta_tb[IFA_ADDRESS]), sizeof(in6)); ifap[i].addr = malloc(sizeof(struct sockaddr_in6)); NET_SOCKADDR_IPv6((struct sockaddr_in6 *) ifap[i].addr,in6); break;#endif /* USE_IPV6 */ }/* if (rta_tb[IFA_LOCAL] == NULL) { rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; if (rta_tb[IFA_LOCAL] == NULL) return 0; } if (rta_tb[IFA_ADDRESS] == NULL) rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL]; switch (ifa->ifa_family) { case AF_INET: memcpy(&NET_GET_ADDR_IPv4(&vifa->local), RTA_DATA(rta_tb[IFA_LOCAL]), alen); if (rta_tb[IFA_ADDRESS]) memcpy(&NET_GET_ADDR_IPv4(&vifa->prefix), RTA_DATA(rta_tb[IFA_ADDRESS]), alen); else vifa->prefix = vifa->local; break; case AF_INET6: memcpy(&NET_GET_ADDR_IPv6(&vifa->local), RTA_DATA(rta_tb[IFA_LOCAL]), alen); if (rta_tb[IFA_ADDRESS]) memcpy(&NET_GET_ADDR_IPv6(&vifa->prefix), RTA_DATA(rta_tb[IFA_ADDRESS]), alen); else vifa->prefix = vifa->local; break; }*/ return 0;}static int store_linkinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg){ int i; struct ifinfomsg *ifi = NLMSG_DATA(n); struct rtattr *rta[IFLA_MAX+1]; if (n->nlmsg_type != RTM_NEWLINK) return 0; if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi))) { errno = 0; return -1; } parse_rtattr(rta, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n)); if (rta[IFLA_IFNAME] == NULL || rta[IFLA_MTU] == NULL) return 0; i = ifi->ifi_index; if (i >= MAX_INTERFACES) return 0; ifap[i].flags = ifi->ifi_flags; ifap[i].mtu = *(unsigned*)RTA_DATA(rta[IFLA_MTU]); return 0;}voidlinux_init(){ static int once = FALSE; struct rtnl_handle rth; if (once) return; if (FAILED(rtnl_open(&rth, 0))) return; /* Read list of links */ if (FAILED(rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK))) return; if (FAILED(rtnl_dump_filter(&rth, store_linkinfo, NULL))) return; /* Now get protocol information */ if (FAILED(rtnl_wilddump_request(&rth, AF_INET, RTM_GETADDR))) return; if (FAILED(rtnl_dump_filter(&rth, store_addrinfo, NULL))) return;#ifdef USE_IPV6 if (FAILED(rtnl_wilddump_request(&rth, AF_INET6, RTM_GETADDR))) return; if (FAILED(rtnl_dump_filter(&rth, store_addrinfo, NULL))) return;#endif /* USE_IPV6 */ rtnl_close(&rth); once = TRUE;}#endif /* linux */#ifdef sunstruct 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)]; 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; return(ifs);}#endif /* sun */#endif /* __FreeBSD__ */#if (defined(__FreeBSD__) || defined(sun))voidif_freenameindex(struct if_nameindex *p){}#endif /* (defined(__FreeBSD__) || defined(sun)) */unsigned intif_nametoindex(const char *ifname){ struct if_nameindex *p,*q; unsigned int index = 0; p = if_nameindex(); if (p == NULL) return(index); for (q = p;q->if_name != NULL; q++) if (strncmp(ifname,q->if_name,IFNAMSIZ) == 0) { index = q->if_index; break; } if_freenameindex(p); return(index);}char *if_indextoname(unsigned int ifindex,char *ifname){ struct if_nameindex *p,*q; char *name = NULL; p = if_nameindex(); if (p == NULL) return(name); for (q = p;q->if_name != NULL; q++) if (ifindex == q->if_index) { strncpy(ifname,q->if_name,IFNAMSIZ); name = ifname; break; } if_freenameindex(p); return(name);}#ifdef sunconst 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); }}intinet_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); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -