📄 rsvp_api.c
字号:
/* * @(#) $Id: rsvp_api.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//************************ rsvp_api.c ******************************** * * * Routines to handle application program interface of rsvpd * * messages. * * * * * *********************************************************************//**************************************************************************** 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/uio.h> /* external declarations */int refresh_api();void rsvp_resv_err(int, int, int, FiltSpecStar *, struct packet *);void rsvp_path_err(int, int, int, struct packet *);u_long Styleid_to_Optvec[];int writev();extern char *style_names[];void rapi_fmt_flowspec(rapi_flowspec_t *, char *, int);void rapi_fmt_tspec(rapi_tspec_t *, char *, int);void rapi_fmt_adspec(rapi_adspec_t *, char *, int);void rapi_fmt_filtspec(rapi_filter_t *, char *, int);int New_Adspec(ADSPEC *);Session * locate_session(SESSION *);char * cnv_flags(char *, u_char);int api_refresh_t;/* forward declarations */static void send_to_api(int, rsvp_resp *, int);static void print_api_request(rsvp_req *, int, int);void api_PATH_EVENT_upcall(Session *);void api_PATH_EVENT_init(Session *, int);void api_PATH_EVENT_upcall1(Session *, int, int);void api_RESV_EVENT_upcall(Session *, RSB *);void api_RESV_EVENT_upcall_stat(Session *, RSB *);void api_RESV_EVENT_upcall1(Session *, RSB *, int);void api_PATH_ERR_upcall(struct packet *);void api_RESV_ERR_upcall(struct packet *);static void upcall_to_appl(rsvp_resp *, int, FILTER_SPEC *, int);static void upcall_to_sid(rsvp_resp *, int, int);int api_prepare_path(rsvp_req *, int, api_rec *, struct packet *);int api_prepare_resv(rsvp_req *, api_rec *, struct packet *);int api_new_packet(struct packet *, int, int);int api_tear_oldresv(struct packet *, struct packet *);int api_status(rsvp_req *);int api_dest_status(Session *, rsvp_req *);int api_get_flows(Object_header *, rsvp_req *, struct packet *);int Move_spec_api2d(rapi_flowspec_t *, FLOWSPEC *);char * Move_spec_d2api(FLOWSPEC *, rapi_flowspec_t *);int Move_tspec_api2d(rapi_tspec_t *, SENDER_TSPEC *);char * Move_tspec_d2api(SENDER_TSPEC *, rapi_tspec_t *);int Move_adspec_api2d(rapi_adspec_t *, ADSPEC *);char * Move_adspec_d2api(ADSPEC *, rapi_adspec_t *);int Move_filter_api2d(rapi_filter_t *, FILTER_SPEC *, int);char * Move_filter_d2api(FILTER_SPEC *, rapi_filter_t *);Session * locate_api_session(rsvp_req *, int);void log_api_event(int, char *, net_addr *, int, const char *, int, int);void api_tear_path(api_rec *);void api_tear_resv(api_rec *);void api_free_packet(struct packet *);void api_ERR_upcall_common(rsvp_resp *, struct packet *);int path_set_laddr(rapi_filter_t *);void hton_api_resp(rsvp_resp *, int);int ntoh_rapi_flowspec(IS_specbody_t *);int hton_rapi_flowspec(IS_specbody_t *);int ntoh_rapi_adspec(IS_adsbody_t *);int hton_rapi_adspec(IS_adsbody_t *);static int resp_session_assign(rsvp_resp *resp, SESSION *session);int net_addr_assign_api_addr(net_addr *addr,const api_addr *x, int udp);/* Macro used in api_prepare_xxxx to add an object to API packet and * to the map of the packet. The map address is 'var'; the object * has class (typedef) 'cls' and ctype (value) 'ctype'. */#define New_Object(var, cls, ctype) \ Init_Object(objp, cls, ctype); \ var = (cls *) objp; \ objp = Next_Object(objp);#define New_VObject(var, cls, ctype, len) \ Init_Var_Obj(objp, cls, ctype,len); \ var = (cls *) objp; \ objp = Next_Object(objp);/* * Array to translate style ID into option vector */u_long Styleid_to_Optvec [] = {/* 0 unused */ 0, /* 1 WF */ STYLE_WF, /* 2 FF */ STYLE_FF, /* 3 SE */ STYLE_SE };/* Define all-api-session value for session id parameter */#define ALL_SID -1/* * process_api_req(): Process request from API client, received over Unix * socket. Return -1 if API session should be closed. * sid = my local handle. */intprocess_api_req(int sid, rsvp_req *req, int len) { api_rec *recp = &api_table[sid]; common_header *hdrp; struct packet new_pkt; int rc; Session *destp; if (IsDebug(DEBUG_ALL)) { print_api_request(req, len, sid); if (l_debug >= LOG_HEXD && len > 0) hexf(stderr, (char *) req, len); } if (len != 0 && (req->rq_version > VERSION_API || req->rq_version < VERSION_APImin)) { log(LOG_ERR, 0, "API: bad version %d\n", req->rq_version); return (-1); /* Close it */ } if (len == 0 || req->rq_type == API_CLOSE) { /* * Close: Session close requested, or client terminated. * If there is stored Path (Resv) message, turn it into a * PathTear (ResvTear) message and procsss it as input. */ api_tear_path(recp); api_tear_resv(recp); return(-1); /* Caller will delete session & timer */ } switch (req->rq_type) { case API2_REGISTER: /* REGISTER command handles 3 different functions: * (1) Session registration (nflwd=0 & no Path state) * (2) New Sender defn (nflwd=1) * (3) Teardown sender (nflwd=0, path state exists) */ net_addr_assign_api_addr(&recp->api_dest,&req->rq_dest,1); recp->api_protid = (req->rq_protid)?req->rq_protid: RSVP_DFLT_PROTID; if (req->rq_nflwd == 0) { /* * No sender descriptor => New registration * or teardown request */ hdrp = recp->api_p_packet.pkt_data; if (hdrp == NULL||hdrp->rsvp_type != RSVP_PATH) { /* * No path state exists => New session * registration. If there is already path * state, trigger path event upcall. */ recp->api_flags = req->rq_flags & ~(API_DIR_SEND|API_DIR_RECV|API_NET_BO); if (NetByteOrderReq(req)) recp->api_flags |= API_NET_BO; destp = locate_api_session(req, (recp->api_flags&RAPI_GPI_SESSION)); if (destp) api_PATH_EVENT_init(destp, sid); return(0); /* None in place, just ignore */ } /* * Turn path state into PathTear message, send it, * and then free API packet buffer & map. If there * is no resv state either, stop refresh timer. */ recp->api_flags &= ~API_DIR_SEND; api_tear_path(recp); if (recp->api_r_packet.pkt_data == NULL) del_from_timer((char *) (unsigned long) sid, TIMEV_API); return(0); } /* else, we are registering a sender. Set up virtual Path * message. */ recp->api_flags |= API_DIR_SEND; hdrp = recp->api_p_packet.pkt_data; if (hdrp == NULL) { /* Allocate space for a packet buffer. (Use max * message size; could compute actual size) XXX */ if (api_new_packet(&recp->api_p_packet, 1, MAX_PKT) < 0) return(-1); } rc = api_prepare_path(req, len, recp, &recp->api_p_packet); if (rc == 0) { /* There was a client error. Delete packet. */ api_free_packet(&recp->api_p_packet); return(0); } else if (rc < 0) { /* There was internal error. Return -1 => caller * will close the API socket. */ return(-1); } recp->api_p_packet.pkt_ttl = recp->api_p_packet.pkt_data->rsvp_snd_TTL; /* * We finished updating API state, now handle the request * itself */ refresh_api(sid); break; case API2_RESV: /* Reservation request. */ hdrp = recp->api_r_packet.pkt_data; if (req->rq_nflwd == 0) { recp->api_flags &= ~API_DIR_RECV; /* * No flow descriptors => teardown request */ if (hdrp == NULL||hdrp->rsvp_type != RSVP_RESV) return(0); /* None in place, just ignore */ /* Send ResvTear and free Resv pkt buff and * map. If there is no path state either, stop * refresh timer. */ api_tear_resv(recp); if (recp->api_p_packet.pkt_data == NULL) del_from_timer((char *) (unsigned long) sid, TIMEV_API); return(0); } /* Initialize local packet struct with new data * buffer and map, then call api_prepare_resv() to * move request data into it. */ recp->api_flags |= API_DIR_RECV; if (api_new_packet(&new_pkt, req->rq_nflwd, Max_rsvp_msg) < 0) return(-1); rc = api_prepare_resv(req, recp, &new_pkt); if (rc == 0) { /* There was a client error. Delete packet. */ api_free_packet(&recp->api_r_packet); return(0); } else if (rc < 0) { /* There was internal error. Return -1 => caller * will close the API socket. */ return(-1); } /* If already have Resv, this is a modification; * tear down state that is being removed, and then * free old data buffer and map. */ if (hdrp) { if (api_tear_oldresv(&recp->api_r_packet, &new_pkt)<0) return(-1); } /* Move pointers to data and map into API record */ recp->api_r_packet.pkt_data = new_pkt.pkt_data; recp->api_r_packet.pkt_map = new_pkt.pkt_map; recp->api_r_packet.pkt_len = new_pkt.pkt_len; recp->api_r_packet.pkt_order = BO_HOST; recp->api_r_packet.pkt_flags = 0; recp->api_r_packet.pkt_ttl = 0; /* * We finished updating API state; now handle the request * itself */ refresh_api(sid); /* * Delete any CONFIRM object, which is single-shot. */ recp->api_r_packet.pkt_map->rsvp_confirm = NULL; break; default: log(LOG_ERR, 0, "API: Bad rq_type=%d\n", req->rq_type); return (-1); } add_to_timer((char *) sid, TIMEV_API, api_refresh_t); dump_ds(0); return (0);}/* Allocate new packet buffer and new map for API. * (Use max message size; could compute actual size) XXX */intapi_new_packet(struct packet *pkt, int nflwd, int data_len) { common_header *hdrp; packet_map *mapp; int map_len = Map_Length(nflwd); if ((hdrp = (common_header *) malloc(data_len))==NULL || (mapp = (packet_map *) malloc(map_len))==NULL) { Log_Mem_Full("API send/resv req"); return (-1); } pkt->pkt_offset = 0; pkt->pkt_map = mapp; pkt->pkt_data = hdrp; pkt->pkt_len = 0; pkt->pkt_flags = pkt->pkt_ttl = 0; pkt->pkt_order = BO_HOST; memset((char *)mapp, 0, sizeof(packet_map)); return(0);}voidapi_tear_path(api_rec *recp) { common_header *hdrp = recp->api_p_packet.pkt_data; if (!hdrp) return; hdrp->rsvp_type = RSVP_PATH_TEAR; recp->api_p_packet.pkt_map->rsvp_msgtype = RSVP_PATH_TEAR; rsvp_pkt_process(&recp->api_p_packet, NULL, api_num); api_free_packet(&recp->api_p_packet);}voidapi_tear_resv(api_rec *recp) { common_header *hdrp = recp->api_r_packet.pkt_data; if (!hdrp) return; hdrp->rsvp_type = RSVP_RESV_TEAR; recp->api_r_packet.pkt_map->rsvp_msgtype = RSVP_RESV_TEAR; /* * Note that the RSVP spec is designed to allow us to make a valid * ResvTear msg from a Resv msg, by just changing the message type. * We could explicitly delete the flowspec from the ResvTear, but * it's better to exercise the logic that ignores the flowspec. */ rsvp_pkt_process(&recp->api_r_packet, NULL, api_num); api_free_packet(&recp->api_r_packet);}voidapi_free_packet(struct packet *pkt) { if (pkt->pkt_data) free(pkt->pkt_data); if (pkt->pkt_map) free(pkt->pkt_map); pkt->pkt_data = NULL; pkt->pkt_map = NULL; pkt->pkt_len = 0;}/* Tear down API state in o_pkt that does not appear in n_pkt. */intapi_tear_oldresv(struct packet *o_pkt, struct packet *n_pkt) { int oi, oj, nk; style_t style = Style(o_pkt); o_pkt->pkt_map->rsvp_msgtype = RSVP_RESV_TEAR; if (style != Style(n_pkt)) { /* Styles differ. Just tear down old Resv. */ rsvp_pkt_process(o_pkt, NULL, api_num); api_free_packet(o_pkt); return(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -