📄 rsvp_netio.c
字号:
/* * @(#) $Id: rsvp_netio.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//************************ rsvp_netio.c ****************************** * * * Network I/O routines * * * *********************************************************************//**************************************************************************** RSVPD -- ReSerVation Protocol Daemon USC Information Sciences Institute Marina del Rey, California Original Version: Shai Herzog, Nov. 1993. Current Version: Steven Berson & Bob Braden, May 1996. Copyright (c) 1996 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 "rsvp_daemon.h"#include "rsvp_api.h"#include "rapi_lib.h"#include <sys/stat.h>#include <fcntl.h>#if (defined(linux) && defined(USE_IPV6))#include <netinet/ip6.h>#endif /* (defined(linux) && defined(USE_IPV6)) */#if (defined(SOLARIS) && defined(USE_IPV6))struct ip6_hdr { union { struct ip6_hdrctl { u_int32_t ip6_un1_flow; /* 24 bits of flow-ID */ u_int16_t ip6_un1_plen; /* payload length */ u_int8_t ip6_un1_nxt; /* next header */ u_int8_t ip6_un1_hlim; /* hop limit */ } ip6_un1; u_int8_t ip6_un2_vfc; /* 4 bits version, 4 bits priority */ } ip6_ctlun; struct in6_addr ip6_src; /* source address */ struct in6_addr ip6_dst; /* destination address */};#define ip6_vfc ip6_ctlun.ip6_un2_vfc#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim#endif /* (defined(SOLARIS) && defined(USE_IPV6)) */#if (defined(freebsd) && defined(USE_IPV6))#define STEVENS_API#include <netinet/ip6.h>#endif /* (defined(freebsd) && defined(USE_IPV6)) */#define UCAST_TTL 63/* Sockets and addresses */struct in_addr encap_group; /* Gu */u_int16_t encap_port; /* Pu */u_int16_t encap_portp; /* Pu' */net_addr *encap_router;net_addr encap_mc_addr;#ifdef USE_IPV6struct in6_addr encap_group6; /* Gu */net_addr encap_mc_addr6;#endif /* USE_IPV6 *//* External declarations */extern char *Type_name[];extern int Test_mode;extern net_addr *tsttun_vec;extern int shift;extern int bmptoif(bitmap *);extern int rsrr_route_query(void*,void *,net_addr *,net_addr *,int,int *,bitmap *);/* forward declarations */static int send_pkt(net_addr *to,net_addr *from,void *msg,int len, int vif,int infn,int hops,int ra);static int IsLocal(net_addr *,int *);static net_addr * udp_addr(net_addr *to,int port);static net_addr * encap_addr(net_addr *to);static int rsvp_pkt_process_1(struct packet *, net_addr *, int);static int udp_input(net_addr *from,char *msg,int len,net_if *inf);static int consume_input(struct packet *packet,net_addr *from,net_if *inf);static int raw_input_ipv4(net_addr *from,char *msg,int len,net_if *inf);#ifdef USE_IPV6static int raw_input_ipv6(net_addr *from,char *msg,int len,net_if *inf);#endif /* USE_IPV6 *//* * send_pkt_out_if(): Send (unicast) RSVP packet to specified previous * hop via specified physical interface (or -1). * * [The outgoing interface is not strictly required to send * unicast messages, but do need it to choose encryption key.] */intsend_pkt_out_if( int outif, RSVP_HOP *hopp, struct packet *pkt) { net_addr *to; net_addr *src = NULL; int mode = 0; assert(!IsHopAPI(hopp)); to = hop_addr(hopp); pkt->pkt_ttl = UCAST_TTL; if (outif >= 0) src = get_if(outif); Incr_ifstats(outif, rsvpstat_msgs_out[pkt->pkt_map->rsvp_msgtype]); mode = build_send_pkt(outif, to, src, pkt); if (IsDebug(DEBUG_ALL)) { char tmp[32]; if (outif >= 0) sprintf(tmp, "%d=>%s > %.16s/%d\n", outif, IF_NAME(outif), net_addr_host(to), pkt->pkt_ttl); else sprintf(tmp, "> %.16s/%d\n", net_addr_host(to), pkt->pkt_ttl); log_event(LOGEV_Send_UDP+mode-1, Type_name[pkt->pkt_map->rsvp_msgtype], pkt->pkt_map->rsvp_session, tmp); if (IsDebug(DEBUG_IO)) print_rsvp(pkt); } return(0);}/* * send_pkt_to(): * Send an RSVP packet to specified inet_addr:port entity. * This is typically used for UDP diagnostics. * Rsvptrace uses this to send UDP DREQ packets. * outif is typically -1. For multicast destinations, it has * the usual meaning. */ intsend_pkt_to( int outif, net_addr *toaddr, struct packet *pkt) { net_addr *srcaddrp = NULL; int mode = 0; switch(NET_GET_TYPE(toaddr)) { case NET_ADDR_UDP_IPv4: assert((NET_GET_ADDR_IPv4(toaddr)).s_addr != INADDR_ANY); assert((NET_GET_ADDR_UDP_IPv4(toaddr)).sin_port != 0); /* TTL setup is only for unicast packets. If this was a diagnostics reply to * a multicast address, ttl would have already been set. */ if(!IN_IS_ADDR_MULTICAST(&NET_GET_ADDR_IPv4(toaddr))) pkt->pkt_ttl = UCAST_TTL; if (outif >= 0) srcaddrp = get_if(outif); break ; case NET_ADDR_UDP_IPv6:/* IPv6 is currently not yet expected to be used by diagnostics */ break ; default: break ; } /* The PKTFLG_NOENCAP helps override the RSVP UDP encapsulation rules * for the diagnostics reply scenario. In this case, a UDP DREP has to * be sent to the diagnostic requester's ephemeral UDP port */ pkt->pkt_flags |= PKTFLG_NOENCAP ; Incr_ifstats(outif, rsvpstat_msgs_out[pkt->pkt_map->rsvp_msgtype]); mode = build_send_pkt(outif, toaddr, srcaddrp, pkt); if (IsDebug(DEBUG_ALL)) { char tmp[32]; if (outif >= 0) sprintf(tmp, "%d> %.16s/%d\n", outif, net_addr_host(toaddr), pkt->pkt_ttl); else sprintf(tmp, "> %.16s/%d\n", net_addr_host(toaddr), pkt->pkt_ttl); log_event(LOGEV_Send_UDP+mode-1, Type_name[pkt->pkt_map->rsvp_msgtype], pkt->pkt_map->rsvp_session, tmp); if (IsDebug(DEBUG_IO)) print_rsvp(pkt); } if (mode < 0) return(-1) ; return(0);}/* * send_pkt_out_vif(): Send Path, PathTear, or ResvErr msg with specific * dest and src addresses to specified vif. * * XXX??? If encap_router address is defined, unicast a unicast UDP * XXX??? copy to that address; this is to allow hosts inside a * XXX??? firewall to send a Path message to the first-hop router. */intsend_pkt_out_vif( int vif, Session *destp, FILTER_SPEC *filtp, struct packet *pkt) { net_addr *to; net_addr *src; int mode = 0; assert(!IsNumAPI(vif)); /* Not API */ src = filterspec_addr(filtp); to = session_addr(destp->d_session); if (encap_router != NULL) { /* If a -R cmd-line option was given to specify the address * of an RSVP-capable router, unicast a UDP copy of pkt to * address. Note: this could be generalized to a list. */ pkt->pkt_flags = PKTFLG_USE_UDP; } Incr_ifstats(vif, rsvpstat_msgs_out[pkt->pkt_map->rsvp_msgtype]); mode = build_send_pkt(vif, to, src, pkt); if (mode < 0) return -1; if (IsDebug(DEBUG_ALL)) { char tmp[32]; sprintf(tmp, "%d=>%s > %.16s/%d\n", vif, IF_NAME(vif), net_addr_host(to), pkt->pkt_ttl); log_event(LOGEV_Send_UDP+mode-1, Type_name[pkt->pkt_map->rsvp_msgtype], pkt->pkt_map->rsvp_session, tmp); if (IsDebug(DEBUG_IO)) print_rsvp(pkt); } return(0);}/* * do_sendmsg(): Send buffer containing RSVP message: * * To specified vif; -1 => unspecified (Resv msgs) * * To destination (addr,port) = *to * * From IP source address = *src; NULL => unspecified * * tp specified TTL (unless UDP encaps is used) * * This routine figures out whether UDP and/or raw encapsualated copies * are needed, and chooses the appropriate socket. The socket choice * is quite system-dependent. */intdo_sendmsg( int vif, net_addr *to, net_addr *src, int flags, u_char ttl, u_char *data, int len) { u_char encap_ttl; int mc,local,mode = 0; net_addr *addr; local = IsLocal(to,&mc); if (vif >= 0) { if (!(IF_FLAGS(vif)&IF_FLAG_IFF_UP)) return(0); /* Should never happen? */ if (mc && !(IF_FLAGS(vif)&IF_FLAG_IFF_MC)) return(0); /* Should never happen? */ encap_ttl = if_vec[IF_UNICAST(vif)].if_udpttl; } else encap_ttl = RSVP_TTL_MAX; if (flags & PKTFLG_NOENCAP) {/* send packet to a UDP target with a port that is not Pu or Pu' */ if (mc) encap_ttl = ttl ; if (FAILED(send_pkt(to,src,data,len,mc,vif,encap_ttl,FALSE))) log(LOG_ERR,errno,"send_pkt"); return(1); } if (!net_has_rawmode()) { /* UDP-only host. */ if (mc) { /* Multicast Path msg: => (G*, P) */ addr = encap_addr(to); } else if (vif >= 0 && !local) { /* Unicast Path msg to non-local D => (Ra, Pu) */ if (encap_router == NULL) { log(LOG_ERR,0, "No UDP Encapsulation Router (Ra)"); return(0); } addr = udp_addr(encap_router,encap_port); } else { /* Unicast Path/Resv msg to local D => (D, Pu) */ addr = udp_addr(to,encap_port); } if (FAILED(send_pkt(addr,src,data,len,mc,vif, encap_ttl,FALSE))) log(LOG_ERR,errno,"send_pkt"); return(1); } else { /* * Send raw encapsulation */ if (mc && (vif > shift) && (ttl < vif_list[if_vec[vif].if_index].threshold)) { /* * if it's multicast packet, and vif * is in the virtual interface space, * also the ttl value is less than the * threshold value for that virtual * interface, then we drop the packet * and return */ Incr_ifstats(vif, rsvpstat_path_threshold); return (0); } if (FAILED(send_pkt(to,src,data,len,mc,vif,ttl, (flags & PKTFLG_Send_RA)))) log(LOG_ERR,errno,"send_pkt"); mode = 2; } if (((vif >= 0 && (IF_FLAGS(vif) & IF_FLAG_UseUDP)) || (flags & PKTFLG_USE_UDP)) && local) { /* * Need UDP encapsulation on this interface, but * we are capable of sending raw packets => (D, Pu') */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -