📄 scrapi.c
字号:
#include "scrapi.h"#include <sys/time.h>#ifdef linux#include <linux/sockios.h>#else /* linux */#include <sys/sockio.h>#endif /* linux */#include <arpa/inet.h>#include <net/if.h>#include <netdb.h>#include <strings.h>#include <limits.h>#include <unistd.h>#include <rapi_err.h>/* * @(#) $Id: scrapi.c,v 1.2 2000/08/17 02:11:09 bogawa Exp $ *//**************************************************************************** SCRAPI: A Simplied RSVP API USC Information Sciences Institute Marina del Rey, California Original Version: Bob Lindell, March 1998. Copyright (c) 1998 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.********************************************************************//// XXX this doesn't compile w/ IPV6 set#undef USE_IPV6/****************************************************************************** * * Strictly RFC 2133 * *****************************************************************************/#ifndef INET_ADDRSTRLEN#define INET_ADDRSTRLEN sizeof("XXX.XXX.XXX.XXX")#endif /* INET_ADDRSTRLEN */#ifdef USE_IPV6extern const struct in6_addr in6addr_any;#endif /* USE_IPV6 */#ifdef sunstatic const char * inet_ntop(int af,const void *src,char *dst,size_t size);static int inet_pton(int af,const char *src,void *dst);static struct hostent * gethostbyname2(const char *name,int af);#endif /* sun *//****************************************************************************** * * Extensions to RFC 2133 * *****************************************************************************/#ifdef USE_IPV6#define MAX_ADDRSTRLEN INET6_ADDRSTRLEN#else /* USE_IPV6 */#define MAX_ADDRSTRLEN INET_ADDRSTRLEN#endif /* USE_IPV6 */#define MAX_ADDRPORTSTRLEN (MAX_ADDRSTRLEN + sizeof("/XXXXX"))#define MAX_HOSTSTRLEN MAXHOSTNAMELEN#define MAX_HOSTPORTSTRLEN (MAX_HOSTSTRLEN + sizeof("/XXXXX"))#define IN_IS_ADDR_MULTICAST(x) IN_MULTICAST(ntohl((x)->s_addr))#define IN_ARE_ADDR_EQUAL(x,y) ((x)->s_addr == (y)->s_addr)static const struct in_addr inaddr_any;/****************************************************************************** * * Macros and functions for socket structures. * *****************************************************************************/#ifdef __FreeBSD__#define NET_SOCKADDR_SIZE_IPv4(x) \ { \ (x)->sin_len = sizeof(struct sockaddr_in); \ }#define NET_SOCKADDR_SIZE_IPv6(x) \ { \ (x)->sin6_len = sizeof(struct sockaddr_in6); \ }#else /* __FreeBSD__ */#define NET_SOCKADDR_SIZE_IPv4(x)#define NET_SOCKADDR_SIZE_IPv6(x)#endif /* __FreeBSD__ */#define NET_SOCKADDR_IPv4(x,addr) NET_SOCKADDR_UDP_IPv4(x,addr,htons(0))#define NET_SOCKADDR_UDP_IPv4(x,addr,port) { \ memset((char *) (x),0,sizeof(struct sockaddr_in)); \ (x)->sin_family = AF_INET; \ (x)->sin_addr = addr; \ (x)->sin_port = port; \ NET_SOCKADDR_SIZE_IPv4(x); \ }#ifdef USE_IPV6#define NET_SOCKADDR_IPv6(x,addr) NET_SOCKADDR_UDP_IPv6(x,addr,htons(0))#define NET_SOCKADDR_UDP_IPv6(x,addr,port) { \ memset((char *) (x),0,sizeof(struct sockaddr_in6)); \ (x)->sin6_family = AF_INET6; \ (x)->sin6_addr = addr; \ (x)->sin6_port = port; \ NET_SOCKADDR_SIZE_IPv6(x); \ }#endif /* USE_IPV6 */#define SAP(x) ((struct sockaddr *) (x))#define SAP4(x) ((struct sockaddr_in *) (x))#define SAP6(x) ((struct sockaddr_in6 *) (x))static int sockaddr_equal(const struct sockaddr *x, const struct sockaddr *y);static int sockaddr_equal_wild(const struct sockaddr *x, const struct sockaddr *y);static int sockaddr_assign(struct sockaddr *x,const struct sockaddr *y);/****************************************************************************** * * Useful Definitions and Macros * *****************************************************************************/#ifndef TRUE#define TRUE (0 == 0)#endif /* TRUE */#ifndef FALSE#define FALSE (0 != 0)#endif /* FALSE */#define SYS_ERROR (-1)#define SYS_NOERROR 0#define FAILED(x) ((x) == SYS_ERROR)#define C_MAX(x,y) (((x) >= (y)) ? (x) : (y))#define C_MIN(x,y) (((x) <= (y)) ? (x) : (y))/****************************************************************************** * * SCRAPI and RAPI Definitions and Macros * *****************************************************************************/#define MAXSESSIONS 256#define Object_Type(x) (((rapi_hdr_t *) (x))->form)#define Object_Length(x) (((rapi_hdr_t *) (x))->len)#define Object_Next(type,x) ((type *) (((char *) (x)) + Object_Length(x)))#define MAX_INTERFACES 32#define MIN_PACKET_SIZE 64#define MAX_PACKET_SIZE 576/* * Status bits */#define S_NONE 0x00000000#define S_RESV 0x00000001#define S_SEND_STATES 0x0000000f#define S_PATH 0x00000010#define S_CONFIRM 0x00000020#define S_RECV_STATES 0x000000f0#define S_STATES 0x000000ff#define S_PATH_REQUEST 0x00000100#define S_SEND_REQUESTS 0x00000f00#define S_RESV_REQUEST 0x00001000#define S_RECV_REQUESTS 0x0000f000#define S_REQUESTS 0x0000ff00#define S_PATH_ERROR 0x00010000#define S_SEND_ERRORS 0x000f0000#define S_RESV_ERROR 0x00100000#define S_RECV_ERRORS 0x00f00000#define S_ERRORS 0x00ff0000#define S_OPEN 0x01000000#define S_SEND_NOT_REQUESTS (S_SEND_STATES | S_SEND_ERRORS)#define S_RECV_NOT_REQUESTS (S_RECV_STATES | S_RECV_ERRORS)#define S_SEND_ALL (S_SEND_STATES | S_SEND_REQUESTS | S_SEND_ERRORS)#define S_RECV_ALL (S_RECV_STATES | S_RECV_REQUESTS | S_RECV_ERRORS)struct sender { unsigned long status; rapi_filter_t src; rapi_flowspec_t spec; struct sender *next;};typedef struct sender sender;struct session { unsigned long status; struct SOCKADDR dst; int proto; struct SOCKADDR src; scrapi_style style; enum qos_service_type service; int errno; sender *flows;};typedef struct session session;static FILE *eout = NULL;static FILE *dout = NULL;static session sessions[MAXSESSIONS];static int nsessions = 0;staticchar *errlist[] = { "No error", /* 0 */ "Syscall error, see errno", /* 1 */ "Memory allocation error", /* 2 */ "Invalid parameters", /* 3 */ "Internal SCRAPI error", /* 4 */ "Bad destination address", /* 5 */ "Bad destination port", /* 6 */ "Bad protocol number", /* 7 */ "Bad source address", /* 8 */ "Bad source port", /* 9 */ "Request timed out", /* 10 */ "No RSVP support", /* 11 */ "Too many sessions" /* 12 */};staticint map_errno[] = { SCRAPI_ERRNO_NONE, /* No error */ SCRAPI_ERRNO_PARAM, /* Invalid parameter */ SCRAPI_ERRNO_SESSION, /* Too many sessions */ SCRAPI_ERRNO_INTERNAL, /* Sid out of legal range */ SCRAPI_ERRNO_INTERNAL, /* Wrong n_filter/n_flow for style */ SCRAPI_ERRNO_INTERNAL, /* Illegal reservation style */ SCRAPI_ERRNO_SYSCALL, /* Some sort of syscall error */ SCRAPI_ERRNO_INTERNAL, /* Parm list overflo */ SCRAPI_ERRNO_MEMORY, /* Not enough memory */ SCRAPI_ERRNO_NORSVP, /* Daemon doesn't respond */ SCRAPI_ERRNO_INTERNAL, /* Object type error */ SCRAPI_ERRNO_INTERNAL, /* Object length error */ SCRAPI_ERRNO_INTERNAL, /* No sender tspec in rapi_sender */ SCRAPI_ERRNO_INTERNAL, /* Intserv format error */ SCRAPI_ERRNO_INTERNAL, /* IPSEC: Conflicting C-type */ SCRAPI_ERRNO_PROTO, /* IPSEC: Protocol not AH|ESP */ SCRAPI_ERRNO_DSTPORT, /* IPSEC: vDstPort is zero */ SCRAPI_ERRNO_PARAM, /* IPSEC: Other parm error */ SCRAPI_ERRNO_INTERNAL, /* Not defined */ SCRAPI_ERRNO_INTERNAL, /* Not defined */ SCRAPI_ERRNO_INTERNAL, /* Not defined */ SCRAPI_ERRNO_SRCADDR, /* Sender addr not my interface */ SCRAPI_ERRNO_INTERNAL, /* Recv addr not my interface */ SCRAPI_ERRNO_DSTPORT /* Sport !=0 but Dport == 0 */};/****************************************************************************** * * Utility functions for filter structures and the like. * *****************************************************************************/#ifdef ISI_TESTstatic int flow_labels = FALSE;voidscrapi_internal_use_flow_labels(int on){ flow_labels = on;}static int gpi = FALSE;voidscrapi_internal_use_gpi(int on){ gpi = on;}#endif /* ISI_TEST */#ifdef USE_IPV6staticintsource_has_label(const struct sockaddr *s,unsigned long *port){#ifdef ISI_TEST if (flow_labels) { *port = htonl(ntohs(scrapi_sockaddr_get_port(s))); return(TRUE); }#endif /* ISI_TEST */ *port = htonl(0); return(FALSE);}#endif /* USE_IPV6 */staticintsource_has_gpi(const struct sockaddr *s,unsigned long *port){#ifdef ISI_TEST if (gpi) { *port = htonl(ntohs(scrapi_sockaddr_get_port(s))); return(TRUE); }#endif /* ISI_TEST */ *port = htonl(0); return(FALSE);}staticrapi_filter_t *filter_from_sockaddr(const struct sockaddr *s){ unsigned long port; static rapi_filter_t f; if (s == NULL) return(NULL); switch (s->sa_family) { case AF_INET: if (source_has_gpi(s,&port)) { Object_Type(&f) = RAPI_FILTERFORM_GPI; Object_Length(&f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_gpi_t); f.rapi_filtgpi4_addr = SAP4(s)->sin_addr; f.rapi_filtgpi4_gpi = port; return(&f); } Object_Type(&f) = RAPI_FILTERFORM_BASE; Object_Length(&f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_base_t); f.rapi_filt4 = *SAP4(s); return(&f);#ifdef USE_IPV6 case AF_INET6: if (source_has_gpi(s,&port)) { Object_Type(&f) = RAPI_FILTERFORM_GPI6; Object_Length(&f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_gpi6_t); f.rapi_filtgpi6_addr = SAP6(s)->sin6_addr; f.rapi_filtgpi6_gpi = port; return(&f); } if (source_has_label(s,&port)) { Object_Type(&f) = RAPI_FILTERFORM_FL6; Object_Length(&f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_fl6_t); f.rapi_filtfl6_addr = SAP6(s)->sin6_addr; f.rapi_filtfl6_fl = port; return(&f); } Object_Type(&f) = RAPI_FILTERFORM_BASE6; Object_Length(&f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_base6_t); f.rapi_filt6 = *SAP6(s); return(&f);#endif /* USE_IPV6 */ default: return(NULL); }}staticintfilter_any(rapi_filter_t *f,int type){ struct SOCKADDR s; Object_Type(f) = type; switch (type) { case RAPI_FILTERFORM_BASE: Object_Length(f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_base_t); NET_SOCKADDR_UDP_IPv4(SAP4(&s),inaddr_any,htons(0)); f->rapi_filt4 = *SAP4(&s); return(TRUE); case RAPI_FILTERFORM_GPI: Object_Length(f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_gpi_t); f->rapi_filtgpi4_addr = inaddr_any; f->rapi_filtgpi4_gpi = htonl(0); return(TRUE);#ifdef USE_IPV6 case RAPI_FILTERFORM_BASE6: Object_Length(f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_base6_t); NET_SOCKADDR_UDP_IPv6(SAP6(&s),in6addr_any,htons(0)); f->rapi_filt6 = *SAP6(&s); return(TRUE); case RAPI_FILTERFORM_GPI6: Object_Length(f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_gpi6_t); f->rapi_filtgpi6_addr = in6addr_any; f->rapi_filtgpi6_gpi = htonl(0); return(TRUE); case RAPI_FILTERFORM_FL6: Object_Length(f) = sizeof(rapi_hdr_t) + sizeof(rapi_filter_fl6_t); f->rapi_filtfl6_addr = in6addr_any; f->rapi_filtfl6_fl = htonl(0); return(TRUE);#endif /* USE_IPV6 */ default: return(FALSE); }}staticintfilter_equal(const rapi_filter_t *x,const rapi_filter_t *y){ if (Object_Type(x) != Object_Type(y)) return(FALSE); switch (Object_Type(x)) { case RAPI_FILTERFORM_BASE: return(sockaddr_equal(SAP(&x->rapi_filt4), SAP(&y->rapi_filt4))); case RAPI_FILTERFORM_GPI: if (!IN_ARE_ADDR_EQUAL(&x->rapi_filtgpi4_addr, &y->rapi_filtgpi4_addr)) return(FALSE); return(x->rapi_filtgpi4_gpi == y->rapi_filtgpi4_gpi);#ifdef USE_IPV6 case RAPI_FILTERFORM_BASE6: return(sockaddr_equal(SAP(&x->rapi_filt6), SAP(&y->rapi_filt6))); case RAPI_FILTERFORM_GPI6: if (!IN6_ARE_ADDR_EQUAL(&x->rapi_filtgpi6_addr, &y->rapi_filtgpi6_addr)) return(FALSE); return(x->rapi_filtgpi6_gpi == y->rapi_filtgpi6_gpi); case RAPI_FILTERFORM_FL6: if (!IN6_ARE_ADDR_EQUAL(&x->rapi_filtfl6_addr, &y->rapi_filtfl6_addr)) return(FALSE); return(x->rapi_filtfl6_fl == y->rapi_filtfl6_fl);#endif /* USE_IPV6 */ default: return(FALSE); }}staticintfilter_equal_wild(const rapi_filter_t *x,const rapi_filter_t *y){ if (Object_Type(x) != Object_Type(y)) return(FALSE); switch (Object_Type(x)) { case RAPI_FILTERFORM_BASE: return(sockaddr_equal_wild(SAP(&x->rapi_filt4), SAP(&y->rapi_filt4))); case RAPI_FILTERFORM_GPI: if (!IN_ARE_ADDR_EQUAL(&x->rapi_filtgpi4_addr, &y->rapi_filtgpi4_addr)) return(FALSE); if (x->rapi_filtgpi4_gpi == htonl(0)) return(TRUE); if (y->rapi_filtgpi4_gpi == htonl(0)) return(TRUE); return(x->rapi_filtgpi4_gpi == y->rapi_filtgpi4_gpi);#ifdef USE_IPV6 case RAPI_FILTERFORM_BASE6: return(sockaddr_equal_wild(SAP(&x->rapi_filt6), SAP(&y->rapi_filt6))); case RAPI_FILTERFORM_GPI6: if (!IN6_ARE_ADDR_EQUAL(&x->rapi_filtgpi6_addr, &y->rapi_filtgpi6_addr)) return(FALSE); if (x->rapi_filtgpi6_gpi == htonl(0)) return(TRUE); if (y->rapi_filtgpi6_gpi == htonl(0)) return(TRUE); return(x->rapi_filtgpi6_gpi == y->rapi_filtgpi6_gpi); case RAPI_FILTERFORM_FL6: if (!IN6_ARE_ADDR_EQUAL(&x->rapi_filtfl6_addr, &y->rapi_filtfl6_addr)) return(FALSE); if (x->rapi_filtfl6_fl == htonl(0)) return(TRUE); if (y->rapi_filtfl6_fl == htonl(0)) return(TRUE); return(x->rapi_filtfl6_fl == y->rapi_filtfl6_fl);#endif /* USE_IPV6 */ default: return(FALSE); }}/****************************************************************************** * * Utility functions for sender information. * *****************************************************************************/staticsender *get_sender(rapi_sid_t sid,const rapi_filter_t *src){ rapi_filter_t host; session *sp; sender *s,*w; sp = &sessions[sid]; for (s = sp->flows;s != NULL;s = s->next) if (filter_equal(&s->src,src)) return(s); s = (sender *) malloc(sizeof(sender)); s->src = *src; s->status = S_NONE; /* * Apply wild src status. */ filter_any(&host,Object_Type(src)); for (w = sp->flows;w != NULL;w = w->next) { /* * Wild src ports take precedence over wild srcs. */ if (filter_equal_wild(src,&w->src)) { s->status |= w->status & S_REQUESTS; break; } if (filter_equal(&host,&w->src)) s->status |= w->status & S_REQUESTS; } s->next = sp->flows; sp->flows = s; return(s);}staticvoidset_sender(rapi_sid_t sid,rapi_filter_t *src,rapi_flowspec_t *spec){ rapi_flowspec_t *r; qos_flowspecx_t *q; qos_tspecx_t *t; session *sp; sender *s; t = &((rapi_tspec_t *) spec)->tspecbody_qosx; if (t->spec_type != QOS_TSPEC) return; sp = &sessions[sid]; s = get_sender(sid,src); r = &s->spec; Object_Type(r) = RAPI_FLOWSTYPE_Simplified; Object_Length(r) = sizeof(rapi_flowspec_t); q = &r->specbody_qosx; q->spec_type = sp->service; q->xspec_r = t->xtspec_r; q->xspec_R = t->xtspec_r; q->xspec_S = 0; q->xspec_b = t->xtspec_b; q->xspec_p = t->xtspec_p; q->xspec_m = t->xtspec_m; q->xspec_M = t->xtspec_M; s->status |= S_PATH;}staticvoidmod_sender(sender *s,enum qos_service_type service,unsigned long status){ if (status == S_NONE) { /* * Must retain PATH state status when we turn off * a reservation. */ s->status &= ~S_RECV_ALL | S_PATH; return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -