📄 rsvp_trans.c
字号:
/* * @(#) $Id: rsvp_trans.c,v 1.8 2000/06/21 00:51:49 wenqing Exp $ *//*********************** rsvp_trans.c ******************************** * * * System Independent Interface to Network and Transport Layers * * * *********************************************************************//**************************************************************************** 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 <arpa/inet.h>#include <netdb.h>#include <net/if.h>#include <netinet/udp.h>#include <sys/time.h>#include <sys/uio.h>#include <sys/file.h>#include <sys/resource.h>#include <stdio.h>#include <errno.h>#include <unistd.h>#include <memory.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <signal.h>#ifdef __FreeBSD__#include <net/if_dl.h>#endif /* __FreeBSD__ */#include "rsvp_socks.h"#include "rsvp_trans.h"#ifndef IPPROTO_RSVP#define IPPROTO_RSVP 46#endif /* IPPROTO_RSVP */#ifdef SO_REUSEPORT#define SO_REUSEXXXX SO_REUSEPORT#else /* SO_REUSEPORT */#define SO_REUSEXXXX SO_REUSEADDR#endif /* SO_REUSEPORT *//* support old spec */#ifdef USE_IPV6#ifndef IPV6_ADD_MEMBERSHIP#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP#endif /* IPV6_ADD_MEMBERSHIP */#endif /* USE_IPV6 */#ifndef IP_PKTINFO#ifdef IP_RECVIF#define in_pktinfo sockaddr_dl#define ipi_ifindex sdl_index#define IP_PKTINFO IP_RECVIF#endif /* IP_RECVIF */#endif /* IP_PKTINFO */#ifndef IPV6_PKTINFO#ifdef IPV6_RECVIF#define in6_pktinfo sockaddr_dl#define ipi6_ifindex sdl_index#define IPV6_PKTINFO IPV6_RECVIF#endif /* IPV6_RECVIF */#endif /* IPV6_PKTINFO *//* FreeBSD workaround for broken IPV6_PKTINFO */#ifdef __FreeBSD__#ifdef IPV6_RECVIF#define in6_pktinfo sockaddr_dl#define ipi6_ifindex sdl_index#undef IPV6_PKTINFO#define IPV6_PKTINFO IPV6_RECVIF#endif /* IPV6_RECVIF */#endif /* __FreeBSD__ */#ifdef sun#if (defined(__SVR4) || defined(__svr4__))#define SOLARIS#else /* (defined(__SVR4) || defined(__svr4__)) */#define SunOS#endif /* (defined(__SVR4) || defined(__svr4__)) */#endif /* sun */#ifdef SunOSextern int ioctl(int,int,caddr_t);extern int socket(int,int,int);extern int setsockopt(int,int,int,char *,int);extern int getsockname(int,struct sockaddr *,int *);extern int bind(int,struct sockaddr *,int);extern int recvfrom(int,char *,int,int,struct sockaddr *,int *);extern int select(int,fd_set *,fd_set *,fd_set *,struct timeval *);extern void bzero(char *,int);extern int on_exit(void (*procp)(),caddr_t);extern int sendmsg(int,struct msghdr *,int);extern int getrlimit(int,struct rlimit *);extern int setrlimit(int,struct rlimit *);#endif /* SunOS *//* * This module exports an interface for performing network I/O of * datagrams over different protocols. All system specific * implementations of this functionality are opaque to the layers * above this module. This module could be further divided into * generic IP protocol support and the actual system dependent * network I/O functionaliy. There does not seem to be any * benefit at this point since IP is the only network protocol * defined for RSVP. */#if sun#define msg_control msg_accrights#define msg_controllen msg_accrightslen#endif /* sun */#ifdef linux/* The following definition might need to be uncommented if /bits/in.h or other similar files in your linux system not defining this struct.struct in_pktinfo{ int ipi_ifindex; struct in_addr ipi_spec_dst; struct in_addr ipi_addr;};*/#define uh_sport source#define uh_dport dest#define uh_ulen len#define uh_sum check#endif /* linux */typedef int (*callback)(int);FILE *debug_file = NULL ;#ifdef ISI_TEST/*** FILE *debug_file = stdout; ***/#endif/* Static variables: record state local to this module. * * o interface[fd]: Vector of net_if structs; per fd. * o finalize[fd]: Addr to be called to delete fd, or null; per fd * o fset[]: bit vector specifying full set of send or receive sockets. * o rset[]: Select bit vector for receive * o protocol_type[fd]: net_addr type corresponding to fd; per fd. * o ulist[net_addr type] = fd to use for sending on default interface * o fd_pu, fd_pup: fds to receive on RSVP Pu, Pu' UDP encaps ports * * There are additional static variables if !defined(IP_DSTOPTS) */static fd_set rset, fset;static int ulist[NET_ADDR_SIZE];static net_addr_type protocol_type[FD_SETSIZE];static net_if interface[FD_SETSIZE];static callback finalize[FD_SETSIZE];static int rawmode = TRUE;static int closed = TRUE;static int ipproto_rsvp = IPPROTO_RSVP;static net_if unknown;static int pid = SYS_ERROR;static int fd_pu, fd_pup;static struct in_addr maddr; /* RSVP G* multicast address *//* Forward Declarations * */static int failed(int fd);static void init();static void final();static void adjust(net_addr *addr,net_addr_type type);static int receive(int fd,net_addr *from,void *msg,int len,net_if *inf);static int add_interface(net_if *inf);static int del_interface(net_if *inf);static void fds_print(FILE *, char *);static int send_ipv4(net_addr_type type,struct sockaddr_in *to, struct sockaddr_in *from,void *msg,int len,net_if *inf, u_char hops,int ra);static int set_ancillary_data_ipv4(struct msghdr *hdr,net_addr_type type, struct sockaddr_in *to,struct sockaddr_in *from, void *msg,int len,net_if *inf,u_char hops,int ra);static int init_ancillary_data_ipv4(int fd);static int socket_ipv4(int type,int proto,net_addr_type atype);static int socket_recv_rsvp_ipv4(int proto);static int socket_recv_udp_ipv4(struct sockaddr_in *addr);static int join_multicast_ipv4(int fd,net_if *inf,struct in_addr *g);static int drop_multicast_ipv4(int fd,net_if *inf,struct in_addr *g);static int drop_all_multicast_ipv4(int fd);static int rsvp_on_ipv4(int fd);static int rsvp_off_ipv4(int fd);static int add_if_ipv4(net_if *inf,struct in_addr *g);static int del_if_ipv4(net_if *inf,struct in_addr *g);static int add_vif_ipv4(net_if *inf);static int del_vif_ipv4(net_if *inf);static int rsvp_vif_off_ipv4(int fd);#ifdef USE_IPV6static int fd6_pu,fd6_pup;static struct in6_addr maddr6;static int send_ipv6(net_addr_type type,struct sockaddr_in6 *to, struct sockaddr_in6 *from,void *msg,int len,net_if *inf, u_char hops,int ra);static int set_ancillary_data_ipv6(struct msghdr *hdr,net_addr_type type, struct sockaddr_in6 *to,struct sockaddr_in6 *from, void *msg,int len,net_if *inf,u_char hops,int ra);static int init_ancillary_data_ipv6(int fd);static int socket_ipv6(int type,int proto,net_addr_type atype);static int socket_recv_rsvp_ipv6(int proto);static int socket_recv_udp_ipv6(struct sockaddr_in6 *addr);static int join_multicast_ipv6(int fd,net_if *inf,struct in6_addr *g);static int drop_multicast_ipv6(int fd,net_if *inf,struct in6_addr *g);static int drop_all_multicast_ipv6(int fd);static int rsvp_on_ipv6(int fd);static int rsvp_off_ipv6(int fd);static int add_if_ipv6(net_if *inf,struct in6_addr *g);static int del_if_ipv6(net_if *inf,struct in6_addr *g);static int initialize(int pu,int pup,struct in_addr *g,struct in6_addr *g6);#else /* USE_IPV6 */static int initialize(int pu,int pup,struct in_addr *g);#endif /* USE_IPV6 *//* * Special case initialization: only UDP. (This routine is not * currently used) */intnet_init_udp_only(net_addr *addr4){ int fd,size,status = SYS_NOERROR; net_addr *iaddr; struct sockaddr_in addr;#ifdef USE_IPV6 struct sockaddr_in6 addr6;#endif /* USE_IPV6 */ init(); rawmode = FALSE; /* Receive RSVP/UDP/IPv4 (Any Interface) */ iaddr = net_get_default_interface(); if ((iaddr != NULL) && (NET_GET_TYPE(iaddr) == NET_ADDR_IPv4)) { NET_SOCKADDR_IPv4(&addr,NET_GET_ADDR_IPv4(iaddr)); } else { NET_SOCKADDR_IPv4(&addr,inaddr_any); } fd = socket_recv_udp_ipv4(&addr); /* Send RSVP/UDP/IPv4 (Any Interface) */ ulist[NET_ADDR_UDP_IPv4] = fd; if (FAILED(fd)) status = SYS_ERROR; else { size = sizeof(addr); if (!FAILED(getsockname(fd,(struct sockaddr *) &addr,&size))) NET_SET_ADDR_UDP_IPv4(addr4,addr); }#ifdef USE_IPV6 /* Receive RSVP/UDP/IPv6 (Any Interface) */ NET_SOCKADDR_IPv6(&addr6,in6addr_any); fd = socket_recv_udp_ipv6(&addr6); /* Send RSVP/UDP/IPv6 (Any Interface) */ ulist[NET_ADDR_UDP_IPv6] = fd; if (FAILED(fd)) status = SYS_ERROR;#endif /* USE_IPV6 */ return(status);}/* Standard initialization. * Set up receive sockets and fds, then call initialize() * to set up send sockets and fds. */int#ifdef USE_IPV6net_init(int pu,int pup,struct in_addr *g,struct in6_addr *g6,int async)#else /* USE_IPV6 */net_init(int pu,int pup,struct in_addr *g,int async)#endif /* USE_IPV6 */{ int fd,status = SYS_NOERROR; struct sockaddr_in addr; struct protoent *p;#ifdef USE_IPV6 struct sockaddr_in6 addr6;#endif /* USE_IPV6 */ init(); maddr = *g; p = getprotobyname("rsvp"); if (p != NULL) ipproto_rsvp = p->p_proto; if (async) { pid = getpid(); if (FAILED(pid)) return(SYS_ERROR); } /* * Send and Receive Raw RSVP/IPv4 (Any Interface) * If Raw socket call fails, sets rawmode == FALSE * Enable RSVP intercept for receiving raw. */ fd = socket_recv_rsvp_ipv4(ipproto_rsvp); ulist[NET_ADDR_IPv4] = fd; if (rawmode && FAILED(fd)) status = SYS_ERROR; /* * Send and Receive Multicast RSVP/UDP/IPv4 [Pu] (Any Interface) */ NET_SOCKADDR_UDP_IPv4(&addr, inaddr_any, pu); fd_pu = socket_recv_udp_ipv4(&addr); ulist[NET_ADDR_UDP_IPv4] = fd_pu; if (FAILED(fd_pu)) status = SYS_ERROR; /* * Receive Multicast RSVP/UDP/IPv4 [Pu'] (Any Interface) */ if (!rawmode) { NET_SOCKADDR_UDP_IPv4(&addr, inaddr_any, pup); fd_pup = socket_recv_udp_ipv4(&addr); if (FAILED(fd_pup)) status = SYS_ERROR; }#ifdef USE_IPV6 maddr6 = *g6; /* Receive RSVP/IPv6 (Any Interface) */ fd = socket_recv_rsvp_ipv6(ipproto_rsvp); /* Send RSVP/IPv6 (Any Interface) */ ulist[NET_ADDR_IPv6] = fd; if (rawmode && FAILED(fd)) status = SYS_ERROR; /* Receive Multicast RSVP/UDP/IPv6 [Pu] (Any Interface) */ NET_SOCKADDR_UDP_IPv6(&addr6,in6addr_any,pu); fd6_pu = socket_recv_udp_ipv6(&addr6); /* Send RSVP/UDP/IPv6 (Any Interface) */ ulist[NET_ADDR_UDP_IPv6] = fd6_pu; if (FAILED(fd6_pu)) status = SYS_ERROR; /* Receive Multicast RSVP/UDP/IPv6 [Pu'] (Any Interface) */ if (!rawmode) { NET_SOCKADDR_UDP_IPv6(&addr6,in6addr_any,pup); fd6_pup = socket_recv_udp_ipv6(&addr6); if (FAILED(fd6_pup)) status = SYS_ERROR; } /* * Now call initialize() to set up send sockets and fds. */ if (FAILED(initialize(pu,pup,g,g6))) status = SYS_ERROR;#else /* USE_IPV6 */ if (FAILED(initialize(pu,pup,g))) status = SYS_ERROR;#endif /* USE_IPV6 */ return(status);}/* * Shutdown network I/O subsystem. */intnet_final(){ int fd,status = SYS_NOERROR; if(closed) return(SYS_NOERROR); for (fd = 0;fd < FD_SETSIZE; fd++) if (FD_ISSET(fd,&fset)) { if (finalize[fd] != NULL) if(FAILED((*finalize[fd])(fd))) status = SYS_ERROR; FD_CLR(fd,&fset); if(FAILED(close(fd))) status = SYS_ERROR; } closed = TRUE; pid = SYS_ERROR; return(status);}intnet_has_rawmode(){ return(rawmode);}intnet_poll_list(fd_set *set){ if (debug_file) fds_print(debug_file, "@ net_poll_list"); *set = rset; return(SYS_NOERROR);}/* * This is how the application tells us which multicast interfaces * to listen for UDP datagrams to G*. */intnet_add_interfaces(int n,net_if *list){ int i,status = SYS_NOERROR; for (i = 0;i < n; i++) if (FAILED(add_interface(&list[i]))) status = SYS_ERROR; return(status);}intnet_del_interfaces(int n,net_if *list){ int i,status = SYS_NOERROR; for (i = 0;i < n; i++) if (FAILED(del_interface(&list[i]))) status = SYS_ERROR; return(status);}/* Some receive bit has appeared in select; do another select() to * find it, and then call receive(fd,...) to read msg and len and to * set inf and from. */intnet_recv(net_addr *from,void *msg,int len,net_if *inf){ int fd,n; fd_set lrset; struct timeval zero; timerclear(&zero); lrset = rset; n = select(FD_SETSIZE,&lrset,(fd_set *) NULL,(fd_set *) NULL,&zero); if (n < 1) return(n); for (fd = 0;fd < FD_SETSIZE; fd++) if (FD_ISSET(fd,&lrset)) return(receive(fd,from,msg,len,inf)); return(0);}/* * Send datagram using the appropriate transport protocol, which * is inferred from the address type. Flags interpretation are * protocol specific. Parameters "from" and "inf" can be * optionally set to NULL. */intnet_send(net_addr *to,net_addr *from,void *msg,int len, net_if *inf,u_char hops,int ra){ net_addr_type type; struct sockaddr_in st,sf,*fp = NULL;#ifdef USE_IPV6 struct sockaddr_in6 st6,sf6,*fp6 = NULL;#endif /* USE_IPV6 */ if ((from != NULL) && NET_UNEQUAL_TYPE(to,from)) return(SYS_ERROR); type = NET_GET_TYPE(to); switch (type) { case NET_ADDR_IPv4: NET_SOCKADDR_IPv4(&st,NET_GET_ADDR_IPv4(to)); if (from != NULL) { NET_SOCKADDR_IPv4(&sf, NET_GET_ADDR_IPv4(from)); fp = &sf; } return(send_ipv4(type,&st,fp,msg,len,inf,hops,ra)); case NET_ADDR_UDP_IPv4: st = NET_GET_ADDR_UDP_IPv4(to); if (from != NULL) fp = &NET_GET_ADDR_UDP_IPv4(from); return(send_ipv4(type,&st,fp,msg,len,inf,hops,ra));#ifdef USE_IPV6 case NET_ADDR_IPv6: NET_SOCKADDR_IPv6(&st6,NET_GET_ADDR_IPv6(to)); if (from != NULL) { NET_SOCKADDR_IPv6(&sf6, NET_GET_ADDR_IPv6(from)); fp6 = &sf6; } return(send_ipv6(type,&st6,fp6,msg,len,inf,hops,ra)); case NET_ADDR_UDP_IPv6: st6 = NET_GET_ADDR_UDP_IPv6(to); if (from != NULL) fp6 = &NET_GET_ADDR_UDP_IPv6(from); return(send_ipv6(type,&st6,fp6,msg,len,inf,hops,ra));#endif /* USE_IPV6 */ default: return(SYS_ERROR); }}staticintfailed(int fd){ FD_CLR(fd,&fset); close(fd); return(SYS_ERROR);}staticvoidinit(){ static struct rlimit limits; static int noexit = TRUE; if (noexit) {#ifdef SunOS on_exit(final,0);#else /* SunOS */ atexit(final);#endif /* SunOS */ noexit = FALSE; } if (FAILED(getrlimit(RLIMIT_NOFILE,&limits))) net_error(NET_ERROR_SYSTEM,"getrlimit"); else { limits.rlim_cur = limits.rlim_max; if (FAILED(setrlimit(RLIMIT_NOFILE,&limits))) net_error(NET_ERROR_SYSTEM,"setrlimit"); } FD_ZERO(&rset); FD_ZERO(&fset); NET_SET_TYPE(&unknown,NET_IF_UNKNOWN); closed = FALSE;}staticvoidfinal(){ net_final();}/* adjust(): This little routine "casts" a net_addr into specified type. * Used to set *from net_addr in receive(). * */staticvoidadjust(net_addr *addr,net_addr_type type){ NET_SET_TYPE(addr,type); switch(type) { case NET_ADDR_IPv4: NET_SET_ADDR_IPv4(addr, NET_GET_ADDR_UDP_IPv4(addr).sin_addr); break;#ifdef USE_IPV6 case NET_ADDR_IPv6: NET_SET_ADDR_IPv6(addr, NET_GET_ADDR_UDP_IPv6(addr).sin6_addr); break;#endif /* USE_IPV6 */ default: break; }}staticintadd_interface(net_if *inf){ int rc; switch(NET_GET_TYPE(inf)) { case NET_IF_PHY: switch (NET_GET_TYPE(&NET_GET_IF_PHY_ADDR(inf))) { case NET_ADDR_IPv4: rc = add_if_ipv4(inf,&maddr); break;#ifdef USE_IPV6 case NET_ADDR_IPv6: rc = add_if_ipv6(inf,&maddr6); break;#endif /* USE_IPV6 */ default: return(SYS_ERROR); } break; case NET_IF_VIF: switch (NET_GET_TYPE(&NET_GET_IF_VIF_ADDR(inf))) { case NET_ADDR_IPv4: rc = add_vif_ipv4(inf); break; default: return(SYS_ERROR); } break; default: return(SYS_ERROR); } if (debug_file) fds_print(debug_file, " after Add Interface");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -