/* * @(#) $Id: rapi_lib.c,v 4.43 1998/09/17 21:48:34 kann Exp $ */ /**************************************************************************** RSVPD -- ReSerVation Protocol Daemon USC Information Sciences Institute Marina del Rey, California Original Version: Don Hoffman, Sun Microsystems Current Version: Bob Braden, May 1996. 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. ********************************************************************/ /* History: * Oct 94 Vers 1: Original code written by Don Hoffman @ Sun Microsystems * ??? 95 Vers 2: Updated by Bob Braden @ ISI * Aug 95 Vers 3: Update client calls to match ID07 protocol spec. * Sep 95 Vers 3.10: Add new calls rapi_session(), rapi_sender() as * alternative to rapi_register(). Also, included improvements developed by Joshua Gahm (JBG) at BBN. * Sep 95 Vers 3.11: Include adspecs in upcalls. * Apr 96 Vers 4.0: Remove non-reentrant rapi_errno variable. * Remove obs parameters and add some new ones. * Allow null rapi_sender call to imply path_tear. * Jun 97 Vers 5.01: [Rel4.1a6] Conform to final int-serv specs, and * to coming XOPEN document. * Aug 98 Vers 5.1: [Rel4.2a4] Support network byte order in pipe to * daemon. Require event_rtn param in session call. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "rsvp_socks.h" #include "rsvp.h" #include "rapi_lib.h" #include "rsvp_api.h" #include "rsvp_specs.h" /* IP protocol Ids for IPSEC: should come from some system * file. XXX */ #define IPPROTID_IPSEC_ESP 50 #define IPPROTID_IPSEC_AH 51 /* Serial numbers to use in calls to connect_to_daemon to distinguish UNIX filenames for the pipes. NB: can only have one outstanding DEBUG connection to the server at a time, so not safe for multi-threaded use. */ #define MAIN_RSVP_CONNECTION_SERIAL_NUM 0 #define DEBUG_RSVP_CONNECTION_SERIAL_NUM 1 /* * Define an entry in client session table. */ typedef struct Sid_info { api_addr dest; /* Destination addr, port */ u_char protid; /* Protocol Id */ u_char in_use; /* in-use flag */ u_char flags; /* Session flags */ rapi_event_rtn_t event_rtn; void *event_rtn_arg; } sid_rec; /* * Client session table; index into this table is * the session handle given to application. */ static sid_rec sid_vec[MAX_RAPI_SESS]; /* * Global variables */ static int rapi_errno = RAPI_ERR_OK; static int pid, init_flag = 0; static int max_sid = 0; /* (To shorten linear search time) */ char client_namestr[70]; /* Name of client send of socket */ api_addr api_address2; net_addr api_address; /* Define empty RAPI and API objects: just header (framing) */ int Empty_RObj[2] = {sizeof(rapi_hdr_t), 0}; #define Empty_APIObj Empty_RObj /* empty API object */ #define Empty_Flowspec (rapi_flowspec_t *) &Empty_RObj #define Empty_Filter (rapi_filter_t *) &Empty_RObj /* JBG: the single socket that will be connected to the * RSVP server. All individual sids will have their socket * fields set to this value when they are in use. */ static int rsvp_socket = -1; static int rsvp_socket_refs = 0; #define mark_sid_inuse(sid_to_mark) \ if (! sid_vec[sid_to_mark].in_use) \ rsvp_socket_refs++; \ sid_vec[sid_to_mark].in_use = 1; #define mark_sid_free(sid_to_mark) \ if (sid_vec[sid_to_mark].in_use) \ rsvp_socket_refs--; \ sid_vec[sid_to_mark].in_use = 0; /* * Forward declarations */ static rapi_sid_t common_register(rapi_sid_t, struct sockaddr *, int, rapi_filter_t *, rapi_tspec_t *, rapi_adspec_t *, rapi_policy_t *, int); #ifdef EX_ROUTE static rapi_sid_t common_register1(rapi_sid_t, struct sockaddr *, int, EXROUTE *, rapi_filter_t *, rapi_tspec_t *, rapi_adspec_t *, rapi_policy_t *, int, int); #endif #ifdef LABEL static rapi_sid_t common_register2(rapi_sid_t, struct sockaddr *, int, rapi_filter_t *, rapi_tspec_t *, rapi_adspec_t *, rapi_policy_t *, int, int); #endif static int rapi_dispatch_fd(int); static int Get_free_slot(); static void sig_pipe(int sig); static int init_rapi(); static int connect_to_daemon(int); static int send_req(rsvp_req *, int, long, int); static char *copy_policy_i2d(rapi_policy_t *, rapi_policy_t *, char *, int); #ifdef EX_ROUTE static char *copy_exroute_i2d(EXROUTE *, EXROUTE *, char *, int); #endif #ifdef LABEL static char *copy_labelreq_i2d(int, char*, char*); #endif static char *copy_flowspec_i2d(rapi_flowspec_t *, API_Flowspec *, char *); static char *copy_tspec_i2d(rapi_tspec_t *, API_TSpec *, char *); static char *copy_adspec_i2d(rapi_adspec_t *, API_Adspec *, char *); static char *copy_filterspec_i2d(rapi_filter_t *, API_FilterSpec *, char *); static int copy_flowspec_d2i(API_Flowspec *, rapi_flowspec_t *, char *, int); static int copy_tspec_d2i(API_TSpec *, rapi_tspec_t *, char *, int); static int copy_filterspec_d2i(API_FilterSpec *, rapi_filter_t *, char *); static int copy_adspec_d2i(API_Adspec *, rapi_adspec_t *, char *, int); static char *copy_sender_desc(rapi_filter_t *, rapi_tspec_t *, rapi_adspec_t *, API_FlowDesc *, char *); void sockaddr2filterbase(struct sockaddr *, rapi_filter_t *); int CSZXtoG_spec(qos_flowspecx_t *, IS_specbody_t *); int CSZXtoGen_tspec(qos_tspecx_t *, IS_tspbody_t *); int CSZXtoCL_spec(qos_flowspecx_t *, IS_specbody_t *); int CSZXtoIS_adspec(qos_adspecx_t *, IS_adsbody_t *); int CLtoCSZX_spec(IS_specbody_t *, qos_flowspecx_t *); int GtoCSZX_spec(IS_specbody_t *, qos_flowspecx_t *); int GentoCSZX_tspec(IS_tspbody_t *, qos_tspecx_t *); int IStoCSZX_adspec(IS_adsbody_t *, qos_adspecx_t *); int writev(); int List_Length(char *, int); int vDstPort_OK(api_addr *, int); int api_addr_assign(api_addr *addr,const struct sockaddr *s); int sockaddr_assign(struct sockaddr *s,const api_addr *addr); #ifdef USE_NET_BO void hton_rapi_cmd(rapi_cmd_t *); /* External declarations * */ int hton_rapi_flowspec(); int ntoh_rapi_flowspec(); int hton_rapi_adspec(); int ntoh_rapi_adspec(); #endif /* USE_NET_BO */ #ifdef sun extern int gethostname(char *,int); #endif /* sun */ #define is_valid(sid) (init_flag && sid <= max_sid && (sid_vec[sid].in_use)) #define IS2RAPI_len(x) (4*(x) + sizeof(rapi_hdr_t) + sizeof(IS_main_hdr_t)) #define RAPI2IS_len(y) wordsof((y)- sizeof(rapi_hdr_t) - sizeof(IS_main_hdr_t)) #define API_IsPath(x) ((x)->resp_type == RAPI_PATH_EVENT || \ (x)->resp_type == RAPI_PATH_ERROR || \ (x)->resp_type == RAPI_PATH_STATUS) /* Check "GPI-ness" of filter spec or sender template: it should * have form _GPI or _GPI6 if and only if the session has the GPI * flag on. Return TRUE iff GPI-ness matches. */ #define GPIness_matches(fp) (((flags&RAPI_GPI_SESSION)!=0) == \ ((fp->form == RAPI_FILTERFORM_GPI)|(fp->form == RAPI_FILTERFORM_GPI6))) #define Protid_OK(pid, flags) (!(flags&RAPI_GPI_SESSION) || \ pid == IPPROTID_IPSEC_AH || pid == IPPROTID_IPSEC_ESP) #ifdef EX_ROUTE #define API_REGIS_BUF_EXLEN(p) API_REGIS_BUF_LEN + Obj_Length(p) - 4 #endif /* For IPSEC, (virtual) dest port must be non-zero. * (I have no idea why...!) */ char *rapi_rstyle_names[] = {"?", "WF", "FF", "SE"}; /********************************************************** * Visible RAPI Routines * **********************************************************/ /* rapi_session(): * Register with the RSVP daemon, creating a new API session. * If successful, return local session id, else return -1 and * set error code in variable. */ rapi_sid_t rapi_session( struct sockaddr *dest, /* Destination host, port */ int protid, int flags, rapi_event_rtn_t event_rtn, void * event_rtn_arg, int *errnop) { rapi_sid_t sid = NULL_SID; if (dest == NULL || event_rtn == NULL) { rapi_errno = RAPI_ERR_INVAL; goto exit; } if (!init_flag) { if (init_rapi() < 0) { rapi_errno = RAPI_ERR_NORSVP; goto exit; } } /* Locate empty session slot */ if ((int)(sid = Get_free_slot()) < 0) { rapi_errno = RAPI_ERR_MAXSESS; goto exit; } mark_sid_inuse(sid); /* Mark it in use */ sid_vec[sid].protid = protid; #if defined LABEL sid_vec[sid].flags = (flags &= (RAPI_USE_INTSERV|RAPI_GPI_SESSION|RAPI_LSP_SESSION)); #else sid_vec[sid].flags = (flags &= (RAPI_USE_INTSERV|RAPI_GPI_SESSION)); #endif api_addr_assign(&sid_vec[sid].dest,dest); sid_vec[sid].event_rtn = event_rtn; sid_vec[sid].event_rtn_arg = event_rtn_arg; /* For GPI_SESSION flag (IPSEC), check that protocol Id * is correct for IPSEC. (because the spec calls for it). */ if (!Protid_OK(protid, flags)) { rapi_errno = RAPI_ERR_BADPROTO; goto exit; } if (!vDstPort_OK(&sid_vec[sid].dest, flags)) { rapi_errno = RAPI_ERR_BADVDPORT; goto exit; } rapi_errno = common_register(sid, NULL, flags, NULL, NULL, NULL,NULL, 0); exit: if (rapi_errno != RAPI_ERR_OK) { mark_sid_free(sid); sid = NULL_SID; } if (errnop) *errnop = rapi_errno; return sid; } /* rapi_sender(): * Set/modify sender parameters. */ int rapi_sender( rapi_sid_t sid, int flags, /* Currently, none used */ struct sockaddr *LHost, /* Sender host, port (optional) */ #ifdef EX_ROUTE EXROUTE * sender_ex_route, #endif rapi_filter_t * sender_template, rapi_tspec_t * sender_tspec, rapi_adspec_t * sender_adspec, rapi_policy_t * sender_policy, int ttl #ifdef LABEL , int label_flag #endif ) { rapi_errno = RAPI_ERR_OK; if (!is_valid(sid)) return RAPI_ERR_BADSID; /* sid_vec[sid].flags |= flags; (None defined) */ /* Assumes session and sender flags are distinct. */ if ((LHost||sender_template) && !sender_tspec) return RAPI_ERR_NOTSPEC; #if defined LABEL if (label_flag) sid_vec[sid].flags |= RAPI_LSP_SESSION; #endif #ifdef EX_ROUTE if(sender_ex_route != NULL){ rapi_errno = common_register1(sid, LHost, sid_vec[sid].flags, sender_ex_route, sender_template, sender_tspec, sender_adspec, sender_policy, ttl, label_flag); } else if(label_flag) { rapi_errno = common_register2(sid, LHost, sid_vec[sid].flags, sender_template, sender_tspec, sender_adspec, sender_policy, ttl, label_flag); } else rapi_errno = common_register(sid, LHost, sid_vec[sid].flags, sender_template, sender_tspec, sender_adspec, sender_policy, ttl); #else rapi_errno = common_register(sid, LHost, sid_vec[sid].flags, sender_template, sender_tspec, sender_adspec, sender_policy, ttl); #endif return (rapi_errno); } /* rapi_reserve(): * Make/modify/delete reservation for session. * */ int rapi_reserve( rapi_sid_t sid, int rflags, struct sockaddr * rhost, /* Receiver host (optional) */ rapi_styleid_t styleid, rapi_stylex_t * style_ext, /* style extension */ rapi_policy_t * rcvr_policy, int n_filter, rapi_filter_t * filter_spec_list, int n_flow, rapi_flowspec_t * flowspec_list) { char *req_buf = NULL, *cp, *End_buf; rsvp_req *req = (rsvp_req *) req_buf; int i, len, n1, n2, nflwd, flags; rapi_filter_t *rfiltp; rapi_flowspec_t *rflowp; rapi_errno = RAPI_ERR_OK; if (!is_valid(sid)) return RAPI_ERR_BADSID; /* Check parameters according to style */ flags = sid_vec[sid].flags; /* session flags */ rfiltp = filter_spec_list; rflowp = flowspec_list; nflwd = 0; switch (styleid) { case RAPI_RSTYLE_WILDCARD: if (n_flow == 0) break; /* Teardown case */ if (n_filter < 0 || n_filter > 1 || n_flow != 1) return RAPI_ERR_N_FFS; if (rflowp == NULL) return RAPI_ERR_INVAL; nflwd = 1; break; case RAPI_RSTYLE_FIXED: if (n_flow == 0) break; /* Teardown case */ if (n_filter != n_flow || n_filter <= 0) return RAPI_ERR_N_FFS; if (rfiltp == NULL || rflowp == NULL) return RAPI_ERR_INVAL; nflwd = n_filter; break; case RAPI_RSTYLE_SE: if (n_flow == 0) break; /* Teardown case */ if (n_flow != 1 || n_filter <= 0) { return RAPI_ERR_N_FFS; } if (rfiltp == NULL || rflowp == NULL) return RAPI_ERR_INVAL; nflwd = n_filter; break; default: return RAPI_ERR_BADSTYLE; } /* Must scan parm lists to get total length in order to * dynamically alloc buffer. */ if ((n1 = List_Length( (char *)rflowp, n_flow)) < 0 || (n2 = List_Length( (char *)rfiltp, n_filter)) < 0) { return RAPI_ERR_INVAL; } else len = sizeof(rsvp_req) + n1 + n2 + abs(n_flow - n_filter)*sizeof( Empty_RObj ); if (!(req_buf = malloc(len))) return RAPI_ERR_MEMFULL; req = (rsvp_req *) req_buf; End_buf = req_buf + len; memset((char *)req, 0, len); req->rq_style = (u_char) styleid; req->rq_type = API2_RESV; req->rq_dest = sid_vec[sid].dest; req->rq_protid = sid_vec[sid].protid; if (rhost) api_addr_assign(&req->rq_host, rhost); else req->rq_host = api_address2; req->rq_nflwd = nflwd; #ifdef USE_NET_BO HTON16(req->rq_nflwd); #endif req->rq_flags = (rflags &= (RAPI_REQ_CONFIRM)); cp = copy_policy_i2d(rcvr_policy, req->rq_policy, End_buf, 1); if (!cp) goto exit; /* If n_flow == 0, simply remove existing reservation (without * releasing API session). */ if (n_flow == 0) { req->rq_nflwd = 0; (void)send_req(req, cp - req_buf, sid, rsvp_socket); goto exit; } /* * Copy ({flowspec|EMPTY}, {filter_spec|EMPTY}) pairs * into request. Note that copy_xxxx_i2d() routines * check that there is room in buffer and if not, set * rapi_errno and return NULL. * * copy_flowspec_i2d translates contents into Intserv format. * copy_filterspec_i2d (currently) simply copies without change. */ for (i = 0; i < nflwd; i++) { if (i < n_filter) { if (!GPIness_matches(rfiltp)) { /* The IPSEC document does not say this must be * checked in the API, but for consistency it * should be. */ rapi_errno = RAPI_ERR_GPI_CONFLICT; goto exit; } } cp = (char *)copy_filterspec_i2d( (i < n_filter)? rfiltp : Empty_Filter, (API_FilterSpec *)cp, End_buf); if (!cp) goto exit; cp = copy_flowspec_i2d((i < n_flow)? rflowp : Empty_Flowspec, (API_Flowspec *)cp, End_buf); if (!cp) goto exit; if (i < n_filter) rfiltp = (rapi_filter_t *) After_RAPIObj(rfiltp); if (i < n_flow) rflowp = (rapi_flowspec_t *) After_RAPIObj(rflowp); } (void)send_req(req, cp - req_buf, sid, rsvp_socket); exit: if (req_buf) free(req_buf); return rapi_errno; } /* rapi_release(): * Delete API session and free session handle. */ int rapi_release(rapi_sid_t sid) { char req_buf[MAX_MSG]; /* TBD: dyn alloc */ rsvp_req *req = (rsvp_req *) req_buf; if (!is_valid(sid)) return RAPI_ERR_BADSID; memset(req_buf, 0, sizeof req_buf); /* Redundant, but cautious */ req->rq_nflwd = 0; req->rq_type = API_CLOSE; (void)send_req(req, sizeof(rsvp_req), sid, rsvp_socket); mark_sid_free(sid); return (RAPI_ERR_OK); } /* rapi_getfd(): * Return file descriptor for socket used now. */ int rapi_getfd(rapi_sid_t sid) { if (!is_valid(sid)) return -1; return rsvp_socket; } /* rapi_dispatch(): * Dispatch upcalls. */ int rapi_dispatch() { fd_set tmp_fds; int fd_wid; struct timeval tout; rapi_errno = RAPI_ERR_OK; if (rsvp_socket == -1) return RAPI_ERR_OK; FD_ZERO(&tmp_fds); FD_SET(rsvp_socket, &tmp_fds); fd_wid = rsvp_socket+1; memset(&tout, 0, sizeof(tout)); /* Poll for input ready on socket */ if (select(fd_wid, &tmp_fds, NULL, NULL, &tout) <= 0) return RAPI_ERR_OK; if (FD_ISSET(rsvp_socket, &tmp_fds)) return(rapi_dispatch_fd(rsvp_socket)); return RAPI_ERR_OK; } int rapi_version() { #if (defined(SOLARIS) && defined(RTAP)) init_rapi(); #endif /* (defined(SOLARIS) && defined(RTAP)) */ return RAPI_VERSION; } #ifdef ISI_TEST /* rapi_status(): * Trigger Path Event and/or Resv Event upcalls for specified sid, * or, if sid = 0, all sid's in this process. */ int rapi_status( rapi_sid_t sid, int flags) /* Direction flags */ { char req_buf[MAX_MSG]; rsvp_req *req = (rsvp_req *) req_buf; rapi_errno = RAPI_ERR_OK; if (sid && !is_valid(sid)) { return RAPI_ERR_BADSID; } memset((char *)req, 0, sizeof(req_buf)); req->rq_type = API2_STAT; if (sid) req->rq_dest = sid_vec[sid].dest; /* already in host BO */ req->rq_flags = flags; (void)send_req(req, sizeof(rsvp_req), sid, rsvp_socket); return (rapi_errno); } #endif /* ISI_TEST */ /* The following routine is not part of the official RAPI interface. * It is a management interface to rsvpd. */ rapi_sid_t rapi_rsvp_cmd(rapi_cmd_t *cmd, int *errnop) { char *req_buf; rsvp_req *req; int lsid = NULL_SID; int old = 0; char *cp; int tmp_socket = -1; /* temporary socket to */ /* be used in sending debug cmd */ int n; rapi_errno = RAPI_ERR_OK; if (init_flag == 0) { if (init_rapi()<0) { rapi_errno = RAPI_ERR_NORSVP; goto exit; } } n = sizeof(int)*cmd->rapi_cmd_len; if (!(req_buf = malloc(n+sizeof(rsvp_req)))) { rapi_errno = RAPI_ERR_MEMFULL; goto exit; } /* Use any free sid entry */ if ((lsid = Get_free_slot()) < 0) { rapi_errno = RAPI_ERR_MAXSESS; goto exit; } mark_sid_inuse(lsid); req = (rsvp_req *) req_buf; req->rq_type = API_DEBUG; cp = req_buf + sizeof(rsvp_req); memcpy(cp, cmd, n); #ifdef USE_NET_BO hton_rapi_cmd((rapi_cmd_t *)cp); #endif cp += n; /* Grab a temporary socket to connect to the daemon so that * we can safely expect a reply to our request as the next * thing sent along on the socket. */ tmp_socket = connect_to_daemon(DEBUG_RSVP_CONNECTION_SERIAL_NUM); if (tmp_socket < 0) { rapi_errno = RAPI_ERR_NORSVP; } else { send_req(req, cp-req_buf, lsid, tmp_socket); close(tmp_socket); /* get rid of the tmp socket */ } mark_sid_free(lsid); exit: if (errnop) *errnop = rapi_errno; if (req_buf) free(req_buf); return old; } /********************************************************** * Initialization and I/O Routines * **********************************************************/ /* Common routine to format a REGISTER request and send it to * the daemon. Returns rapi_errno. * common_register1 is a slitely modified version of common_registe . * The modification was necessary for the explicit routing */ #ifdef EX_ROUTE rapi_sid_t common_register1( rapi_sid_t sid, struct sockaddr *LHost, /* Source host, port (optional) */ int flags, /* Session and sender flags */ EXROUTE * sender_ex_route, rapi_filter_t * sender_template, rapi_tspec_t * sender_tspec, rapi_adspec_t * sender_adspec, rapi_policy_t * sender_policy, int ttl, int label_flag) { char req_buf[API_REGIS_BUF_EXLEN(sender_ex_route)]; char *End_buf = &req_buf[API_REGIS_BUF_EXLEN(sender_ex_route)]; rsvp_req *req = (rsvp_req *) req_buf; char *cp; rapi_filter_t fl, *flp; rapi_errno = RAPI_ERR_OK; /* * Build REGISTER request and send to daemon */ memset((char *)req, 0, API_REGIS_BUF_EXLEN(sender_ex_route)); req->rq_type = API2_REGISTER; req->rq_dest = sid_vec[sid].dest; req->rq_protid = sid_vec[sid].protid; req->rq_nflwd = 0; req->rq_flags = flags; req->rq_ttl = ttl; if (LHost != NULL || sender_template != NULL) { /* rapi_sender call. */ cp = copy_policy_i2d(sender_policy, req->rq_policy, End_buf, 0); if (!cp) return rapi_errno; /* * If sender_template is NULL, use LHost. */ if (sender_template == NULL) { /* GPI session must have sender template */ if (flags&RAPI_GPI_SESSION) return RAPI_ERR_GPISESS; sockaddr2filterbase(LHost, flp = &fl); } else { if (!GPIness_matches(sender_template)) return RAPI_ERR_GPI_CONFLICT; flp = sender_template; } cp = copy_exroute_i2d(sender_ex_route,req->rq_rlist,End_buf, 0); #ifdef LABEL cp = copy_labelreq_i2d(label_flag, cp, End_buf); #endif cp = (char *) copy_sender_desc(flp, sender_tspec, sender_adspec, (API_FlowDesc *) cp, End_buf); if (!cp) return rapi_errno; req->rq_nflwd = 1; } else { cp = copy_policy_i2d(NULL, req->rq_policy, End_buf, 0); if (!cp) return rapi_errno; } /* XXX No code here yet to pass adspec */ send_req(req, cp-req_buf, sid, rsvp_socket); return(rapi_errno); } #endif #ifdef LABEL rapi_sid_t common_register2( rapi_sid_t sid, struct sockaddr *LHost, /* Source host, port (optional) */ int flags, /* Session and sender flags */ rapi_filter_t * sender_template, rapi_tspec_t * sender_tspec, rapi_adspec_t * sender_adspec, rapi_policy_t * sender_policy, int ttl, int label_flag) { char req_buf[API_REGIS_BUF_LEN+16]; char *End_buf = &req_buf[API_REGIS_BUF_LEN+16]; rsvp_req *req = (rsvp_req *) req_buf; char *cp; rapi_filter_t fl, *flp; rapi_errno = RAPI_ERR_OK; /* * Build REGISTER request and send to daemon */ memset((char *)req, 0, API_REGIS_BUF_LEN+16); req->rq_type = API2_REGISTER; req->rq_dest = sid_vec[sid].dest; req->rq_protid = sid_vec[sid].protid; req->rq_nflwd = 0; req->rq_flags = flags; req->rq_ttl = ttl; if (LHost != NULL || sender_template != NULL) { /* rapi_sender call. */ cp = copy_policy_i2d(sender_policy, req->rq_policy, End_buf, 0); if (!cp) return rapi_errno; /* * If sender_template is NULL, use LHost. */ if (sender_template == NULL) { /* GPI session must have sender template */ if (flags&RAPI_GPI_SESSION) return RAPI_ERR_GPISESS; sockaddr2filterbase(LHost, flp = &fl); } else { if (!GPIness_matches(sender_template)) return RAPI_ERR_GPI_CONFLICT; flp = sender_template; } #ifdef EX_ROUTE cp = copy_exroute_i2d(NULL, (EXROUTE *)cp, End_buf, 0); #endif cp = copy_labelreq_i2d(label_flag, cp, End_buf); cp = (char *) copy_sender_desc(flp, sender_tspec, sender_adspec, (API_FlowDesc *) cp, End_buf); if (!cp) return rapi_errno; req->rq_nflwd = 1; } else { cp = copy_policy_i2d(NULL, req->rq_policy, End_buf, 0); if (!cp) return rapi_errno; } /* XXX No code here yet to pass adspec */ send_req(req, cp-req_buf, sid, rsvp_socket); return(rapi_errno); } #endif /* Common routine to format a REGISTER request and send it to * the daemon. Returns rapi_errno. */ rapi_sid_t common_register( rapi_sid_t sid, struct sockaddr *LHost, /* Source host, port */ int flags, /* Session or sender flags */ rapi_filter_t * sender_template, /* (Optional) */ rapi_tspec_t * sender_tspec, rapi_adspec_t * sender_adspec, rapi_policy_t * sender_policy, int ttl) { char req_buf[API_REGIS_BUF_LEN]; char *End_buf = &req_buf[API_REGIS_BUF_LEN]; rsvp_req *req = (rsvp_req *) req_buf; char *cp; rapi_filter_t fl, *flp; rapi_errno = RAPI_ERR_OK; /* * Build REGISTER request and send to daemon */ memset((char *)req, 0, API_REGIS_BUF_LEN); req->rq_type = API2_REGISTER; req->rq_dest = sid_vec[sid].dest; req->rq_protid = sid_vec[sid].protid; req->rq_nflwd = 0; req->rq_flags = flags; req->rq_ttl = ttl; if (LHost != NULL || sender_template != NULL) { /* rapi_sender call. */ cp = copy_policy_i2d(sender_policy, req->rq_policy, End_buf, 0); if (!cp) return rapi_errno; /* * If sender_template is NULL, use LHost. */ if (sender_template == NULL) { /* GPI session must have sender template */ if (flags&RAPI_GPI_SESSION) return RAPI_ERR_GPISESS; sockaddr2filterbase(LHost, flp = &fl); } else { if (!GPIness_matches(sender_template)) return RAPI_ERR_GPI_CONFLICT; flp = sender_template; } #ifdef EX_ROUTE cp = copy_exroute_i2d(NULL, (EXROUTE *)cp, End_buf, 0); #endif cp = (char *) copy_sender_desc(flp, sender_tspec, sender_adspec, (API_FlowDesc *) cp, End_buf); if (!cp) return rapi_errno; req->rq_nflwd = 1; } else { cp = copy_policy_i2d(NULL, req->rq_policy, End_buf, 0); if (!cp) return rapi_errno; } #ifdef USE_NET_BO HTON16(req->rq_nflwd); #endif send_req(req, cp-req_buf, sid, rsvp_socket); return(rapi_errno); } /* Find and return index of free slot in table, or return -1 if * table is full. If succeeds, clears slot to zero. */ int Get_free_slot() { int sid; /* To avoid ambiguity, we avoid using sid = zero. */ for (sid = 1; sid <= max_sid ; sid++) if (!sid_vec[sid].in_use) return(sid); if (sid < MAX_RAPI_SESS) { max_sid = sid; memset((char *)&sid_vec[sid], 0, sizeof(sid_rec)); return(sid); } return(-1); /* Table full */ } static void sig_pipe(int sig) { /* * This has to be fixed. A SIGPIPE typically means the server * dropped the connection. The client either needs to die, or to try * to reestablish the connection. */ /* * TBD: call client handler with appropriate error */ fprintf(stderr, "Got a SIGPIPE\n"); signal(SIGPIPE, sig_pipe); } static int init_rapi() { struct sockaddr_in x; pid = getpid(); signal(SIGPIPE, sig_pipe); (void)memset((char *) sid_vec, 0, sizeof(sid_vec)); init_flag = 1; rapi_errno = RAPI_ERR_OK; rsvp_socket_refs = 0; NET_SOCKADDR_IPv4(&x,inaddr_any) net_addr_assign(&api_address,(struct sockaddr *) &x); api_addr_assign(&api_address2,(struct sockaddr *) &x); /* Open a single pipe that this process will use * to talk to the rsvp daemon. */ rsvp_socket = connect_to_daemon(MAIN_RSVP_CONNECTION_SERIAL_NUM); return((rsvp_socket < 0) ? -1 : 0); } static struct sockaddr * get_local_address(unsigned short port) { char name[MAXHOSTNAMELEN]; struct hostent *hp; struct in_addr in; static struct sockaddr_in sin; if (FAILED(gethostname(name,MAXHOSTNAMELEN))) return(NULL); if (inet_pton(AF_INET,name,&in) == 1) { NET_SOCKADDR_UDP_IPv4(&sin,in,port); return((struct sockaddr *) &sin); } hp = gethostbyname2(name,AF_INET); if (hp != NULL) { memcpy(&in,hp->h_addr,hp->h_length); NET_SOCKADDR_UDP_IPv4(&sin,in,port); return((struct sockaddr *) &sin); } return(NULL); } static int connect_to_daemon_tcp(int serial_no) { int sock,ret; struct sockaddr *s; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("opening socket"); return (-1); } #ifdef SOLARIS if (fcntl(sock,F_SETFL,fcntl(sock,F_GETFL) | O_NONBLOCK) == -1) { perror("Setting Non-blocking I/O"); return(-1); } #endif /* SOLARIS */ s = get_local_address(hton16(API_PORT)); if (s == NULL) return(-1); ret = connect(sock, s,sizeof(struct sockaddr_in)); #ifdef SOLARIS if ((ret >= 0) || (errno == EINPROGRESS)) { #else /* SOLARIS */ if (ret >= 0) { #endif /* SOLARIS */ return (sock); } close(sock); return (-1); } static int connect_to_daemon_unix(int serial_no) { int sock, ret, addr_len; struct sockaddr_un name, server; if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { perror("opening socket"); return (-1); } sprintf(client_namestr, "%s.%u.%u", LNAME, pid, serial_no); unlink(client_namestr); name.sun_family = AF_UNIX; strcpy(name.sun_path, client_namestr); #ifdef STANDARD_C_LIBRARY addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(name.sun_path)); #else addr_len = sizeof(name.sun_family) + strlen(name.sun_path); #endif #ifdef SOCKADDR_LEN name.sun_len = addr_len; #endif if (bind(sock, (struct sockaddr *) & name, addr_len) < 0) { perror("bind"); goto BadOpen; } #ifdef SOLARIS if (fcntl(sock,F_SETFL,fcntl(sock,F_GETFL) | O_NONBLOCK) == -1) { perror("Setting Non-blocking I/O"); exit(-1); } #endif /* SOLARIS */ server.sun_family = AF_UNIX; strcpy(server.sun_path, SNAME); #ifdef STANDARD_C_LIBRARY addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path)); #else addr_len = sizeof(server.sun_family) + strlen(server.sun_path); #endif #if BSD >= 199103 server.sun_len = addr_len; #endif ret = connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)); #ifdef SOLARIS if ((ret >= 0) || (errno == EINPROGRESS)) { #else /* SOLARIS */ if (ret >= 0) { #endif /* SOLARIS */ unlink(client_namestr); return (sock); } BadOpen: close(sock); unlink(client_namestr); return (-1); } static int connect_to_daemon(int serial_no) { int sock; sock = connect_to_daemon_unix(serial_no); if (sock < 0) return(connect_to_daemon_tcp(serial_no)); return(sock); } /* Send request to daemon. Send 4 bytes containing length of * req structure, followed by req structure itself. * * JBG: added sock as an argument to the following so that the * debug interface can open its own temporary socket and use it. */ static int send_req(rsvp_req * req, int len, long sid, int sock) { struct iovec iov[2]; int nlen = len; req->rq_pid = pid; req->rq_a_sid = sid; req->rq_version = VERSION_API; #ifdef USE_NET_BO HTON32(req->rq_pid); HTON32(req->rq_a_sid); HTON32(nlen); req->rq_flags |= API_NET_BO; #endif iov[0].iov_base = (char *) (&nlen); iov[0].iov_len = sizeof(int); iov[1].iov_base = (char *) req; iov[1].iov_len = len; #ifdef SOLARIS retry: #endif /* SOLARIS */ if (writev(sock, iov, 2) == -1) { #ifdef SOLARIS int retry_cnt = 0; if((errno == EAGAIN) && (retry_cnt++ < 5)) { /* Hack to get around race condition where * we get to this operation before the non-blocking * connect completes. */ sleep(2); goto retry; } #endif /* SOLARIS */ rapi_errno = RAPI_ERR_SYSCALL; } return(0); } int rapi_dispatch_fd(int fd_val) { char *resp_buf = NULL; rsvp_resp *resp; int i, len, n, nr, size; int n_filter, n_flowspec, n_adspec; rapi_filter_t *api_filter = NULL, *tapi_filt; rapi_flowspec_t *api_flowspec = NULL, *tapi_spec; rapi_adspec_t *api_adspec = NULL, *tapi_adspp; char *eapi_filt, *eapi_spec, *eapi_adspp; API_FilterSpec *fltr; API_Flowspec *flow; API_Adspec *adspp; sid_rec *sidp; struct SOCKADDR enode; char *cp; rapi_errno = RAPI_ERR_OK; /* Response is sent as a 4-byte length field followed by * that many bytes of response data. Read length and * then malloc buffer. */ n = read(fd_val, &len, sizeof(int)); #ifdef USE_NET_BO NTOH32(len); #endif if (n == 0) { /* EOF => RSVP daemon is gone... ! */ rapi_errno = RAPI_ERR_NORSVP; goto err_exit; } else if (n < sizeof(int)) { rapi_errno = RAPI_ERR_SYSCALL; goto err_exit; /* some error in the mechanism */ } if (n == -1) { rapi_errno = RAPI_ERR_NORSVP; goto err_exit; } if (!(resp_buf = malloc(len))) { rapi_errno = RAPI_ERR_MEMFULL; goto err_exit; } resp = (rsvp_resp *)resp_buf; nr = len; cp = resp_buf; while (nr) { n = read(fd_val, cp, nr); if (n <= 0) { rapi_errno = RAPI_ERR_NORSVP; goto err_exit; } nr -= n; cp += n; } /* This version always sends in a request in network byte order; * we assume that rsvpd sends a response in network byte order. */ #ifdef USE_NET_BO NTOH32(resp->resp_a_sid); NTOH32(resp->resp_style); NTOH16(resp->resp_errval); NTOH16(resp->resp_nflwd); #endif sidp = &sid_vec[resp->resp_a_sid]; /* XXX should validate a_sid */ sockaddr_assign((struct sockaddr *) &enode,&resp->resp_errnode); if (resp->resp_nflwd == 0) { /* Special case: nflwd == 0; means teardown of state. * Invoke the client's upcall routine */ if (sidp->event_rtn) (*(sidp->event_rtn)) ( (rapi_sid_t) resp->resp_a_sid, (rapi_eventinfo_t) resp->resp_type, resp->resp_style, resp->resp_errcode, resp->resp_errval, (struct sockaddr *) &enode, resp->resp_errflags, 0, NULL, 0, NULL, 0, NULL, sidp->event_rtn_arg ); goto err_exit; } /* Malloc space for filtspec, flowspec, adspec lists for app * * NB: allocating space based on worst case sizes. * XXX Could 'parse' vbl-length info to determine actual sizes */ size = sizeof(rapi_filter_t) * resp->resp_nflwd; if ((api_filter = malloc(size)) == NULL) { rapi_errno = RAPI_ERR_MEMFULL; goto err_exit; } eapi_filt = (char *)api_filter + size; size = sizeof(rapi_flowspec_t) * resp->resp_nflwd; if ((api_flowspec = malloc(size)) == NULL) { rapi_errno = RAPI_ERR_MEMFULL; goto err_exit; } eapi_spec = (char *)api_flowspec + size; /* Copy list of (filterspec, flowspec) pairs into 2 areas */ tapi_filt = api_filter; tapi_spec = api_flowspec; n_filter = n_flowspec = n_adspec = 0; fltr = (API_FilterSpec *) resp->resp_flows; for (i = 0; i < resp->resp_nflwd; i++) { copy_filterspec_d2i(fltr, tapi_filt, eapi_filt); tapi_filt = (rapi_filter_t *) After_RAPIObj(tapi_filt); n_filter++; flow = (API_Flowspec *) After_APIObj(fltr); if (API_IsPath(resp)) { #ifdef USE_NET_BO NTOH_RAPIhdr(flow); if (ntoh_rapi_flowspec( &((API_TSpec *)flow)->tspecbody_IS) < 0) { rapi_errno = RAPI_ERR_INVAL; goto err_exit; } #endif /* USE_NET_BO */ copy_tspec_d2i((API_TSpec*)flow, (rapi_tspec_t *)tapi_spec, eapi_spec, sidp->flags&RAPI_USE_INTSERV); tapi_spec= (rapi_flowspec_t *) After_RAPIObj(tapi_spec); n_flowspec++; } else if (n_flowspec < 1) { #ifdef USE_NET_BO NTOH_RAPIhdr(flow); if (ntoh_rapi_flowspec(&flow->specbody_IS) < 0) { rapi_errno = RAPI_ERR_INVAL; goto err_exit; } #endif /* USE_NET_BO */ copy_flowspec_d2i(flow, tapi_spec, eapi_spec, sidp->flags&RAPI_USE_INTSERV); tapi_spec = (rapi_flowspec_t *) After_RAPIObj(tapi_spec); n_flowspec++; } fltr = (API_FilterSpec *) After_APIObj(flow); } if (API_IsPath(resp) && (char *)fltr - resp_buf < len){ /* * For path event, list of adspecs follows sender * descriptor list. (We make sure there really is * an adspec list, for backwards compatibility). */ size = (MAX_ADSPEC_LEN+sizeof(rapi_hdr_t)) * resp->resp_nflwd; api_adspec = malloc(size); if (api_adspec == NULL) { rapi_errno = RAPI_ERR_MEMFULL; goto err_exit; } eapi_adspp = (char *)api_adspec + size; tapi_adspp = api_adspec; adspp = (rapi_adspec_t *) fltr; for (i = 0; i < resp->resp_nflwd; i++) { #ifdef USE_NET_BO NTOH_RAPIhdr(adspp); if (ntoh_rapi_adspec(&adspp->adspecbody_IS) < 0) { rapi_errno = RAPI_ERR_INVAL; goto err_exit; } #endif /* USE_NET_BO */ copy_adspec_d2i(adspp, tapi_adspp, eapi_adspp, sidp->flags&RAPI_USE_INTSERV); if (adspp->form != RAPI_EMPTY_OTYPE) n_adspec++; /* Count non-empties */ adspp = (API_Adspec *)After_APIObj(adspp); tapi_adspp = (rapi_adspec_t *) After_RAPIObj(tapi_adspp); } /* If list contained only empty objects, pass 0 for n_adspec; * otherwise, pass resp_nflwd. */ if (n_adspec) n_adspec = resp->resp_nflwd; } if (n_filter == 0) { free(api_filter); api_filter = NULL; } if (n_flowspec == 0) { free(api_flowspec); api_flowspec = NULL; } if (n_adspec == 0) { if (api_adspec) free(api_adspec); api_adspec = NULL; } /* Invoke the client's upcall routine */ sockaddr_assign((struct sockaddr *) &enode,&resp->resp_errnode); if (sidp->event_rtn) (*(sidp->event_rtn)) ( (rapi_sid_t) resp->resp_a_sid, (rapi_eventinfo_t) resp->resp_type, resp->resp_style, resp->resp_errcode, resp->resp_errval, (struct sockaddr *)&enode, resp->resp_errflags, n_filter, api_filter, n_flowspec, api_flowspec, n_adspec, api_adspec, sidp->event_rtn_arg ); /* * Upon return, free malloc'd areas */ err_exit: if (api_filter) free(api_filter); if (api_flowspec) free(api_flowspec); if (api_adspec) free(api_adspec); if (resp_buf) free(resp_buf); return (rapi_errno); } /* Scan a given list of N RAPI objects, and compute upper bound on * length after translation to API objects, for buffer allocation. */ int List_Length(char *lcp, int N) { int i; int len = 0; for (i= 0; i < N; i++) { switch (((rapi_hdr_t *)lcp)->form) { case RAPI_EMPTY_OTYPE: break; case RAPI_FILTERFORM_BASE: len += sizeof(rapi_filter_base_t); break; case RAPI_FILTERFORM_GPI: len += sizeof(rapi_filter_gpi_t); break; #ifdef USE_IPV6 case RAPI_FILTERFORM_BASE6: len += sizeof(rapi_filter_base6_t); break; case RAPI_FILTERFORM_GPI6: len += sizeof(rapi_filter_gpi6_t); break; #endif /* USE_IPV6 */ #if defined LABEL case RAPI_FILTERFORM_LSPv4: len += sizeof(rapi_filter_lspv4_t); break; #endif case RAPI_FLOWSTYPE_Simplified: case RAPI_FLOWSTYPE_Intserv: /* IS: The Real Thing */ /* Use max Intserv flowspec size */ len += sizeof(IS_specbody_t); break; default: /* SHOULD NOT HAPPEN */ return -1; } len += sizeof(rapi_hdr_t); /* Common part */ lcp = After_RAPIObj(lcp); } return len; } char * copy_sender_desc( rapi_filter_t * i_filter, rapi_tspec_t * i_tspec, rapi_adspec_t * i_adspec, API_FlowDesc * flwdp, char * endp) { char *cp; if (!i_tspec) i_tspec = (rapi_tspec_t *) &Empty_APIObj; cp = copy_filterspec_i2d(i_filter, (API_FilterSpec *) flwdp, endp); if (!cp) return NULL; cp = copy_tspec_i2d(i_tspec, (API_TSpec *)cp, endp); if (i_adspec) cp = copy_adspec_i2d(i_adspec, (API_Adspec *)cp, endp); return cp; } void sockaddr2filterbase(struct sockaddr *sockp, rapi_filter_t *filtp) { switch(sockp->sa_family) { case AF_INET: filtp->form = RAPI_FILTERFORM_BASE; filtp->len = sizeof(rapi_hdr_t) + sizeof(rapi_filter_base_t); filtp->rapi_filt4 = *(struct sockaddr_in *)sockp; break; #ifdef USE_IPV6 case AF_INET6: filtp->form = RAPI_FILTERFORM_BASE6; filtp->len = sizeof(rapi_hdr_t) + sizeof(rapi_filter_base6_t); filtp->rapi_filt6 = *(struct sockaddr_in6 *)sockp; break; #endif /* USE_IPV6 */ } } int vDstPort_OK(api_addr *addr, int flags) { if (!flags&RAPI_GPI_SESSION) /* We don't do any checking of dest port unless is IPSEC; * the spec says we MAY, but we don't have to. */ return(1); return(addr->port != 0); } /********************************************************************** * COPY-AND-TRANSLATE ROUTINES * * For flowspecs and adspecs, these routines may do serious translation, * since the API protocol assumes Intserv data structure bodies. * For filterspecs, these routines (currently) simply pass through the * RAPI/API object, except they convert byte order if needed. * **********************************************************************/ /* Translate flowspec from user interface format to daemon format, * checking type, length, and for overflow of req message. * Return ptr to next d_spec locn, or NULL if error. */ static char * copy_flowspec_i2d(rapi_flowspec_t * i_spec, API_Flowspec * d_spec, char *endp) { int newL; char *next; switch (i_spec->form) { case RAPI_FLOWSTYPE_Simplified: /* * Simplifed: translate into proper Int-Serv format. */ newL = sizeof(IS_specbody_t)+sizeof(rapi_hdr_t); if ((char *)d_spec+ newL > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } if (RAPIObj_Size(i_spec) < sizeof(qos_flowspecx_t)+sizeof(rapi_hdr_t)) { rapi_errno = RAPI_ERR_OBJLEN; return NULL; } switch (i_spec->specbody_qosx.spec_type) { case QOS_GUARANTEEDX: CSZXtoG_spec(&i_spec->specbody_qosx, &d_spec->specbody_IS); break; case QOS_CNTR_LOAD: CSZXtoCL_spec(&i_spec->specbody_qosx, &d_spec->specbody_IS); break; default: rapi_errno = RAPI_ERR_INVAL; return NULL; } d_spec->form = RAPI_FLOWSTYPE_Intserv; d_spec->len = IS2RAPI_len(d_spec->specbody_IS.ISmh_len32b); #ifdef USE_NET_BO if (hton_rapi_flowspec(&d_spec->specbody_IS) < 0) { rapi_errno = RAPI_ERR_INVAL; return NULL; } #endif /* USE_NET_BO */ break; case RAPI_FLOWSTYPE_Intserv: newL = RAPIObj_Size(i_spec); if ((char *)d_spec + newL > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } /* Check length inside Intserv main header */ if (i_spec->specbody_IS.ISmh_len32b != RAPI2IS_len(newL)) { rapi_errno = RAPI_ERR_OBJLEN; return NULL; } memcpy((char *) d_spec, (char *) i_spec, newL); #ifdef USE_NET_BO if (hton_rapi_flowspec(&d_spec->specbody_IS) < 0) { rapi_errno = RAPI_ERR_INVAL; return NULL; } #endif /* USE_NET_BO */ break; case RAPI_EMPTY_OTYPE: if ((char *)d_spec + sizeof(Empty_RObj) > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } memcpy((char *)d_spec, (char *)&Empty_RObj, sizeof(Empty_RObj)); break; default: rapi_errno = RAPI_ERR_OBJTYPE; return NULL; } next = After_RAPIObj(d_spec); #ifdef USE_NET_BO HTON_RAPIhdr(d_spec); #endif /* USE_NET_BO */ return (next); } /* Translate Tspec from user interface format to daemon format, * checking type, length, and for overflow of req message. * Return ptr to next d_spec locn, or NULL if error. */ static char * copy_tspec_i2d(rapi_tspec_t * i_spec, API_TSpec * d_spec, char *endp) { int printf(); char *next; if ((char *)d_spec + sizeof(rapi_tspec_t) > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } switch (i_spec->form) { case RAPI_FLOWSTYPE_Simplified: printf("Obsolete Tspec form: should be RAPI_TSPECTYPE_Simplified\n"); case RAPI_TSPECTYPE_Simplified: /* * Simplified format: translate into proper Intserv * format. In this case, don't have to supply any values. */ if (RAPIObj_Size(i_spec) < sizeof(qos_tspecx_t)+sizeof(rapi_hdr_t)) { rapi_errno = RAPI_ERR_OBJLEN; return NULL; } switch (i_spec->tspecbody_qosx.spec_type) { case QOS_GUARANTEEDX: case QOS_CNTR_LOAD: case QOS_TSPECX: /* -> Generic Tspec */ CSZXtoGen_tspec(&i_spec->tspecbody_qosx, &d_spec->tspecbody_IS); break; default: rapi_errno = RAPI_ERR_INVAL; return NULL; } d_spec->form = RAPI_TSPECTYPE_Intserv; d_spec->len =IS2RAPI_len(d_spec->tspecbody_IS.IStmh_len32b); #ifdef USE_NET_BO if (hton_rapi_flowspec(&d_spec->tspecbody_IS) < 0) { rapi_errno = RAPI_ERR_INVAL; return NULL; } #endif /* USE_NET_BO */ break; case RAPI_TSPECTYPE_Intserv: /* Set length in Intserv flowspec header */ if (RAPIObj_Size(i_spec) < sizeof(rapi_tspec_t)) { rapi_errno = RAPI_ERR_OBJLEN; return NULL; } i_spec->tspecbody_IS.IStmh_len32b = RAPI2IS_len(RAPIObj_Size(i_spec)); memcpy((char *) d_spec, (char *) i_spec, RAPIObj_Size(i_spec)); #ifdef USE_NET_BO if (hton_rapi_flowspec(&d_spec->tspecbody_IS) < 0) { rapi_errno = RAPI_ERR_INVAL; return NULL; } #endif /* USE_NET_BO */ break; case RAPI_EMPTY_OTYPE: memcpy((char *)d_spec, (char *)&Empty_RObj, sizeof(Empty_RObj)); break; default: rapi_errno = RAPI_ERR_OBJTYPE; return NULL; } next = After_RAPIObj(d_spec); #ifdef USE_NET_BO HTON_RAPIhdr(d_spec); #endif /* USE_NET_BO */ return ( next ); } /* Copy adspec and convert to Intserv format with RAPI framing. * Sets rapi_errno and returns NULL if it fails. */ static char * copy_adspec_i2d(rapi_adspec_t *i_adsp, API_Adspec *d_adsp, char *endp) { char *next; switch (i_adsp->form) { case RAPI_ADSTYPE_Simplified: if ((char *)d_adsp + MAX_ADSPEC_LEN > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } if (CSZXtoIS_adspec(&i_adsp->adspecbody_qosx, &d_adsp->adspecbody_IS)) return NULL; d_adsp->form = RAPI_ADSTYPE_Intserv; d_adsp->len = IS2RAPI_len(d_adsp->adspecbody_IS.adspec_mh.ismh_len32b); #ifdef USE_NET_BO if (hton_rapi_adspec(&d_adsp->adspecbody_IS) < 0) { rapi_errno = RAPI_ERR_INVAL; return NULL; } #endif /* USE_NET_BO */ break; case RAPI_FLOWSTYPE_Intserv: /* Set length in Intserv flowspec header */ if (RAPIObj_Size(i_adsp) > MAX_ADSPEC_LEN) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } i_adsp->adspecbody_IS.adspec_mh.ismh_len32b = RAPI2IS_len(RAPIObj_Size(i_adsp)); memcpy((char *) d_adsp, (char *) i_adsp, RAPIObj_Size(i_adsp)); #ifdef USE_NET_BO if (hton_rapi_adspec(&d_adsp->adspecbody_IS) < 0) { rapi_errno = RAPI_ERR_INVAL; return NULL; } #endif /* USE_NET_BO */ break; case RAPI_EMPTY_OTYPE: memcpy((char *)d_adsp, (char *)&Empty_RObj, sizeof(Empty_RObj)); break; default: rapi_errno = RAPI_ERR_OBJTYPE; return NULL; } next = After_RAPIObj(d_adsp); #ifdef USE_NET_BO HTON_RAPIhdr(d_adsp); #endif /* USE_NET_BO */ return next; } /* * Copy and convert RAPI-format filter spec into daemon format. */ static char * copy_filterspec_i2d(rapi_filter_t * i_filter, API_FilterSpec * d_filter, char *endp) { int newL; char *next; switch (i_filter->form) { case RAPI_FILTERFORM_BASE: newL = sizeof(rapi_filter_base_t)+sizeof(rapi_hdr_t); break; case RAPI_FILTERFORM_GPI: newL = sizeof(rapi_filter_gpi_t)+sizeof(rapi_hdr_t); break; #ifdef USE_IPV6 case RAPI_FILTERFORM_BASE6: newL = sizeof(rapi_filter_base6_t)+sizeof(rapi_hdr_t); break; case RAPI_FILTERFORM_GPI6: newL = sizeof(rapi_filter_gpi6_t)+sizeof(rapi_hdr_t); break; #endif /* USE_IPV6 */ case RAPI_EMPTY_OTYPE: newL = sizeof(rapi_hdr_t); break; #if defined LABEL case RAPI_FILTERFORM_LSPv4: newL = sizeof(rapi_filter_lspv4_t)+sizeof(rapi_hdr_t); break; #endif default: rapi_errno = RAPI_ERR_OBJTYPE; return NULL; } if (RAPIObj_Size(i_filter) != newL) { rapi_errno = RAPI_ERR_OBJLEN; return NULL; } if ((char *)d_filter + RAPIObj_Size(i_filter) > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } memcpy((char *) d_filter, (char *) i_filter, RAPIObj_Size(i_filter)); next = After_RAPIObj(d_filter); #ifdef USE_NET_BO HTON_RAPIhdr(d_filter); #endif /* USE_NET_BO */ return (next); } /* Translate from daemon format to user interface format, checking * for overflow of upcall area. Sets rapi_errno and returns -1 if * error, else returns zero. */ static int copy_flowspec_d2i(API_Flowspec * d_spec, rapi_flowspec_t * i_spec, char *endp, int Use_Intserv) { IS_serv_hdr_t *isshp = (IS_serv_hdr_t *) &d_spec->specbody_IS.spec_u; int rapilen; rapilen = (Use_Intserv)? RAPIObj_Size(d_spec) : sizeof(qos_flowspecx_t) + sizeof(rapi_hdr_t); if ((char *)i_spec + rapilen > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return -1; } i_spec->len = rapilen; if (Use_Intserv) { /* RAPI format is int-serv body with RAPI framing, * that is, we can just copy RAPI object without change. */ memcpy((char *) i_spec, (char *) d_spec, rapilen); return 0; } i_spec->form = RAPI_FLOWSTYPE_Simplified; switch (isshp->issh_service) { case CONTROLLED_LOAD_SERV: CLtoCSZX_spec(&d_spec->specbody_IS, &i_spec->specbody_qosx); return 0; case GUARANTEED_SERV: GtoCSZX_spec(&d_spec->specbody_IS, &i_spec->specbody_qosx); return 0; default: rapi_errno = RAPI_ERR_INTSERV; return -1; } } static int copy_tspec_d2i(API_TSpec * d_spec, rapi_tspec_t * i_spec, char *endp, int Use_Intserv) { IS_serv_hdr_t *isshp = (IS_serv_hdr_t *)&d_spec->tspecbody_IS.tspec_u; int rapilen; rapilen = (Use_Intserv)? RAPIObj_Size(d_spec) : sizeof(qos_tspecx_t) + sizeof(rapi_hdr_t); if ((char *)i_spec + rapilen > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return -1; } i_spec->len = rapilen; if (Use_Intserv) { memcpy((char *) i_spec, (char *) d_spec, rapilen); return 0; } i_spec->form = RAPI_TSPECTYPE_Simplified; switch (isshp->issh_service) { case GENERAL_INFO: GentoCSZX_tspec(&d_spec->tspecbody_IS, &i_spec->tspecbody_qosx); return 0; default: rapi_errno = RAPI_ERR_INTSERV; return -1; } } static int copy_adspec_d2i(API_Adspec * d_adspp, rapi_adspec_t * i_adspp, char *endp, int Use_Intserv) { int rapilen; rapilen = (Use_Intserv)? RAPIObj_Size(d_adspp) : sizeof(qos_adspecx_t) + sizeof(rapi_hdr_t); if ((char *)i_adspp + rapilen > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return -1; } i_adspp->len = rapilen; if (Use_Intserv) { i_adspp->form = RAPI_ADSTYPE_Intserv; memcpy((char *) i_adspp, (char *) d_adspp, rapilen); } else { /* Convert Intserv format to Simplified format. */ i_adspp->form = RAPI_ADSTYPE_Simplified; IStoCSZX_adspec(&d_adspp->adspecbody_IS, &i_adspp->adspecbody_qosx); } return 0; } static int copy_filterspec_d2i(API_FilterSpec * d_filter, rapi_filter_t * i_filter, char *endp) { #ifdef USE_NET_BO NTOH_RAPIhdr(d_filter); #endif /* USE_NET_BO */ if ((char *)i_filter + RAPIObj_Size(d_filter) > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return -1; } memcpy((char *) i_filter, (char *) d_filter, RAPIObj_Size(d_filter)); return 0; } static char * copy_policy_i2d( rapi_policy_t *i_pol, rapi_policy_t *o_pol, char *endp, int policy) { char *next; i_pol = (rapi_policy_t *) &Empty_RObj; /*** ALWAYS EMPTY ! ***/ if ((char *)o_pol + RAPIObj_Size(i_pol) > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } memcpy((char *) o_pol, (char *)i_pol, RAPIObj_Size(i_pol)); next = After_RAPIObj(o_pol); #ifdef USE_NET_BO HTON_RAPIhdr(o_pol); #endif /* USE_NET_BO */ return (next); } /* * Translates the EXROUTE Object from interface into daemon format. */ #ifdef EX_ROUTE static char * copy_exroute_i2d( EXROUTE *i_ex, EXROUTE *o_ex, char *endp, int route) { if (i_ex == NULL) { i_ex = (EXROUTE *) malloc(12); /*** ALWAYS EMPTY ! ***/ bzero(i_ex,12); memcpy((char *) o_ex, (char *)i_ex, 12); return((char*)(o_ex) + 12); } else{ if ((char *)o_ex + Obj_Length(i_ex) > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } } memcpy((char *) o_ex, (char *)i_ex, Obj_Length(i_ex)); return ((char *)(o_ex) + Obj_Length(i_ex)); } #endif /* * Translates the LABEL Object from interface into daemon format. */ #ifdef LABEL static char* copy_labelreq_i2d( int label_flag, char *hptr, char *endp) { Labelreq *label_req; if (label_flag == 1){ label_req = malloc(sizeof(Label)); if ((hptr + 8) > endp) { rapi_errno = RAPI_ERR_OVERFLOW; return NULL; } Obj_Length(label_req) = 8; Obj_CType(label_req) = ctype_Labelreq; Obj_Class(label_req) = class_Label_Request; label_req->reserved = 0; label_req->l3pid = (0x0800); memcpy(hptr, (char *)label_req, Obj_Length(label_req)); return (hptr + Obj_Length(label_req)); } else return hptr; } #endif /* Build (Intserv) Guaranteed Flowspec from Simplified-format flowspec */ int CSZXtoG_spec(qos_flowspecx_t *csxp, IS_specbody_t *ISp) { Guar_flowspec_t *gp = &ISp->spec_u.G_spec; Set_Main_Hdr(&ISp->spec_mh, sizeof(Guar_flowspec_t)); Set_Serv_Hdr(&gp->Guar_serv_hdr, GUARANTEED_SERV, Gspec_len); Set_Parm_Hdr(&gp->Guar_Tspec_hdr, IS_WKP_TB_TSPEC, sizeof(TB_Tsp_parms_t)); gp->Gspec_r = csxp->xspec_r; gp->Gspec_b = csxp->xspec_b; gp->Gspec_p = csxp->xspec_p; gp->Gspec_m = csxp->xspec_m; gp->Gspec_M = csxp->xspec_M; Set_Parm_Hdr(&gp->Guar_Rspec_hdr, IS_GUAR_RSPEC, sizeof(guar_Rspec_t)); gp->Gspec_R = csxp->xspec_R; gp->Gspec_S = csxp->xspec_S; return(0); } /* Build (Intserv) Generic Tspec from Simplified-format Tspec */ int CSZXtoGen_tspec(qos_tspecx_t *csxtp, IS_tspbody_t *IStp) { gen_Tspec_t *gtp = &IStp->tspec_u.gen_stspec; Set_Main_Hdr(&IStp->st_mh, sizeof(gen_Tspec_t)); Set_Serv_Hdr(>p->gen_Tspec_serv_hdr, GENERAL_INFO, gtspec_len); Set_Parm_Hdr(>p->gen_Tspec_parm_hdr, IS_WKP_TB_TSPEC, sizeof(TB_Tsp_parms_t)); gtp->gtspec_r = csxtp->xtspec_r; gtp->gtspec_b = csxtp->xtspec_b; gtp->gtspec_p = csxtp->xtspec_p; gtp->gtspec_m = csxtp->xtspec_m; gtp->gtspec_M = csxtp->xtspec_M; return(0); } /* Build (Intserv) Controlled-Load Flowspec from Simplified-format Flowspec */ int CSZXtoCL_spec(qos_flowspecx_t *csxp, IS_specbody_t *ISp) { CL_flowspec_t *clsp = &ISp->spec_u.CL_spec; Set_Main_Hdr(&ISp->spec_mh, sizeof(CL_flowspec_t)); Set_Serv_Hdr(&clsp->CL_spec_serv_hdr, CONTROLLED_LOAD_SERV, CLspec_len); Set_Parm_Hdr(&clsp->CL_spec_parm_hdr, IS_WKP_TB_TSPEC, sizeof(TB_Tsp_parms_t)); clsp->CLspec_r = csxp->xspec_r; clsp->CLspec_b = csxp->xspec_b; clsp->CLspec_p = csxp->xspec_p; clsp->CLspec_m = csxp->xspec_m; clsp->CLspec_M = csxp->xspec_M; return(0); } /* Map Intserv Guaranteed Flowspec into Simplified format */ int GtoCSZX_spec(IS_specbody_t *ISp, qos_flowspecx_t *csxp) { Guar_flowspec_t *gp = &ISp->spec_u.G_spec; csxp->xspec_r = gp->Gspec_r; csxp->xspec_b = gp->Gspec_b; csxp->xspec_m = gp->Gspec_m; csxp->xspec_M = gp->Gspec_M; csxp->xspec_p = gp->Gspec_p; csxp->xspec_R = gp->Gspec_R; csxp->xspec_S = gp->Gspec_S; csxp->spec_type = QOS_GUARANTEEDX; return(0); } /* Map Intserv Controlled-Load Flowspec into Simplified format * (We don't check format here... assume intserv format is OK) */ int CLtoCSZX_spec(IS_specbody_t *ISp, qos_flowspecx_t *csxp) { CL_flowspec_t *clsp = &ISp->spec_u.CL_spec; csxp->xspec_r = clsp->CLspec_r; csxp->xspec_b = clsp->CLspec_b; csxp->xspec_p = clsp->CLspec_p; csxp->xspec_m = clsp->CLspec_m; csxp->xspec_M = clsp->CLspec_M; csxp->xspec_R = 0; csxp->xspec_S = 0; csxp->spec_type = QOS_CNTR_LOAD; return(0); } /* Map Intserv Generic Tspec into Simplified format Tspec * (We don't check format here... assume intserv format is OK) */ int GentoCSZX_tspec(IS_tspbody_t *IStp, qos_tspecx_t *ctxp) { gen_Tspec_t *gtp = &IStp->tspec_u.gen_stspec; ctxp->xtspec_r = gtp->gtspec_r; ctxp->xtspec_b = gtp->gtspec_b; ctxp->xtspec_p = gtp->gtspec_p; ctxp->xtspec_m = gtp->gtspec_m; ctxp->xtspec_M = gtp->gtspec_M; ctxp->spec_type = QOS_TSPECX; return(0); } #define Move_parm2SF(t, y) siap->y = * (t *) (php+1) /* Map Intserv Adspec into Simplified format Adspec */ int IStoCSZX_adspec(IS_adsbody_t *ISap, qos_adspecx_t *siap) { IS_main_hdr_t *mhp = (IS_main_hdr_t *)ISap; IS_serv_hdr_t *shp = (IS_serv_hdr_t *)(mhp+1); /* Ptr to 1st frag */ IS_serv_hdr_t *lastshp = (IS_serv_hdr_t *) Next_Main_Hdr(mhp); IS_parm_hdr_t *php, *lastphp; memset((char *)siap, 0, sizeof(qos_adspecx_t)); siap->xGaspec_flags = XASPEC_FLG_IGN; siap->xClaspec_flags = XASPEC_FLG_IGN; if (mhp->ismh_version != INTSERV_VERSION0) { return(-1); /* All zero if ill-formed int-serv adspec */ } while (shp < lastshp) { lastphp = (IS_parm_hdr_t *)Next_Serv_Hdr(shp); switch(shp->issh_service) { case GENERAL_INFO: { genparm_parms_t *gp = (genparm_parms_t *)shp; /* * Move default general parameters into default * slots and into service-specific override slots. */ if (shp->issh_flags&ISSH_BREAK_BIT) siap->xaspec_flags = XASPEC_FLG_BRK; siap->xaspec_hopcnt = gp->gen_parm_hopcnt; siap->xaspec_path_bw = gp->gen_parm_path_bw; siap->xaspec_min_latency = gp->gen_parm_min_latency; siap->xaspec_composed_MTU = gp->gen_parm_composed_MTU; /* Also copy general parameters into override * fields, in case they are needed. */ siap->xClaspec_hopcnt = gp-> gen_parm_hopcnt; siap->xClaspec_path_bw = gp-> gen_parm_path_bw; siap->xClaspec_min_latency = gp-> gen_parm_min_latency; siap->xClaspec_composed_MTU = gp-> gen_parm_composed_MTU; siap->xGaspec_hopcnt = gp-> gen_parm_hopcnt; siap->xGaspec_path_bw = gp-> gen_parm_path_bw; siap->xGaspec_min_latency = gp-> gen_parm_min_latency; siap->xGaspec_composed_MTU = gp-> gen_parm_composed_MTU; break; case GUARANTEED_SERV: siap->xGaspec_flags &= ~XASPEC_FLG_IGN; if (shp->issh_flags&ISSH_BREAK_BIT) siap->xGaspec_flags = XASPEC_FLG_BRK; for (php = (IS_parm_hdr_t *)(shp+1); php < lastphp; php = Next_Parm_Hdr(php)) { switch (php->isph_parm_num) { case GUAR_ADSPARM_Ctot: siap->xGaspec_flags |= XASPEC_FLG_PARM; siap->xGaspec_Ctot = *(u_int32_t *)(php+1); break; case GUAR_ADSPARM_Dtot: siap->xGaspec_Dtot = *(u_int32_t *)(php+1); break; case GUAR_ADSPARM_Csum: siap->xGaspec_Csum = *(u_int32_t *)(php+1); break; case GUAR_ADSPARM_Dsum: siap->xGaspec_Dsum = *(u_int32_t *)(php+1); break; case IS_WKP_HOP_CNT: siap->xGaspec_override = 1; Move_parm2SF(u_int16_t, xGaspec_hopcnt); break; case IS_WKP_PATH_BW: siap->xGaspec_override = 1; Move_parm2SF(float32_t, xGaspec_path_bw); break; case IS_WKP_MIN_LATENCY: siap->xGaspec_override = 1; Move_parm2SF(u_int32_t, xGaspec_min_latency); break; case IS_WKP_COMPOSED_MTU: siap->xGaspec_override = 1; Move_parm2SF(u_int32_t, xGaspec_composed_MTU); break; default: break; } } break; } case CONTROLLED_LOAD_SERV: siap->xClaspec_flags &= ~XASPEC_FLG_IGN; if (shp->issh_flags&ISSH_BREAK_BIT) siap->xClaspec_flags = XASPEC_FLG_BRK; for (php = (IS_parm_hdr_t *)(shp+1); php < lastphp; php = Next_Parm_Hdr(php)) { siap->xClaspec_override = 1; switch (php->isph_parm_num) { case IS_WKP_HOP_CNT: siap->xClaspec_hopcnt = *(u_int32_t *)(php+1); break; case IS_WKP_MIN_LATENCY: siap->xClaspec_min_latency = *(u_int32_t *)(php+1); break; case IS_WKP_COMPOSED_MTU: siap->xClaspec_composed_MTU = *(u_int32_t *)(php+1); break; case IS_WKP_PATH_BW: siap->xClaspec_path_bw = *(u_int32_t *)(php+1); break; default: break; } } break; default: break; } shp = (IS_serv_hdr_t *)lastphp; } return (0); } #define Set_Parm(id, t, val) {t *xxx = (t *)(php+1); \ Set_Parm_Hdr(php, id, sizeof(t)); \ *xxx = val; php++; \ cumlen += (sizeof(IS_parm_hdr_t)+sizeof(t));\ php = (IS_parm_hdr_t *)(xxx+1);} /* Map Simplified format Adspec into Intserv Adspec */ int CSZXtoIS_adspec(qos_adspecx_t *siap, IS_adsbody_t *ISap) { IS_main_hdr_t *mhp = (IS_main_hdr_t *)ISap; IS_serv_hdr_t *shp = (IS_serv_hdr_t *)(mhp+1); /* Ptr to 1st frag */ genparm_parms_t *genp; IS_parm_hdr_t *php; /* Parameter pointer */ int cumlen; genp = (genparm_parms_t *)shp; php = (IS_parm_hdr_t *)(shp+1); cumlen = 0; Set_Parm(IS_WKP_HOP_CNT, u_int32_t, siap->xaspec_hopcnt); Set_Parm(IS_WKP_PATH_BW, float32_t, siap->xaspec_path_bw); Set_Parm(IS_WKP_MIN_LATENCY, u_int32_t, siap->xaspec_min_latency); Set_Parm(IS_WKP_COMPOSED_MTU, u_int32_t, siap->xaspec_composed_MTU); Set_Serv_Hdr(shp, GENERAL_INFO, cumlen); #ifdef ISI_TEST if (siap->xaspec_flags & XASPEC_FLG_BRK) Set_Break_Bit(shp); #endif shp = (IS_serv_hdr_t *)(php); if (!(siap->xGaspec_flags & XASPEC_FLG_IGN)) { php = (IS_parm_hdr_t *)(shp+1); cumlen = 0; if (siap->xGaspec_flags & XASPEC_FLG_PARM) { Set_Parm(GUAR_ADSPARM_Ctot, u_int32_t, siap->xGaspec_Ctot); Set_Parm(GUAR_ADSPARM_Dtot, u_int32_t, siap->xGaspec_Dtot); Set_Parm(GUAR_ADSPARM_Csum, u_int32_t, siap->xGaspec_Csum); Set_Parm(GUAR_ADSPARM_Dsum, u_int32_t, siap->xGaspec_Dsum); } #ifdef ISI_TEST if (siap->xGaspec_override) { if (siap->xGaspec_hopcnt != genp->gen_parm_hopcnt) Set_Parm(IS_WKP_HOP_CNT, u_int32_t, siap->xGaspec_hopcnt); if (siap->xGaspec_path_bw != genp->gen_parm_path_bw) Set_Parm(IS_WKP_PATH_BW, float32_t, siap->xGaspec_path_bw); if (siap->xGaspec_min_latency != genp->gen_parm_min_latency) Set_Parm(IS_WKP_MIN_LATENCY, u_int32_t, siap->xGaspec_min_latency); if (siap->xGaspec_composed_MTU != genp->gen_parm_composed_MTU) Set_Parm(IS_WKP_COMPOSED_MTU, u_int32_t, siap->xGaspec_composed_MTU); } #else Set_Break_Bit(shp); /* We do not support GUARANTEED */ #endif } Set_Serv_Hdr(shp, GUARANTEED_SERV, cumlen); if (siap->xGaspec_flags & XASPEC_FLG_BRK) Set_Break_Bit(shp); shp = (IS_serv_hdr_t *)php; if (!(siap->xClaspec_flags & XASPEC_FLG_IGN)) { php = (IS_parm_hdr_t *)(shp+1); cumlen = 0; #ifdef ISI_TEST if (siap->xClaspec_override) { if (siap->xClaspec_hopcnt != genp->gen_parm_hopcnt) Set_Parm(IS_WKP_HOP_CNT, u_int32_t, siap->xClaspec_hopcnt); if (siap->xClaspec_path_bw != genp->gen_parm_path_bw) Set_Parm(IS_WKP_PATH_BW, float32_t, siap->xClaspec_path_bw); if (siap->xClaspec_min_latency != genp->gen_parm_min_latency) Set_Parm(IS_WKP_MIN_LATENCY, u_int32_t, siap->xClaspec_min_latency); if (siap->xClaspec_composed_MTU != genp->gen_parm_composed_MTU) Set_Parm(IS_WKP_COMPOSED_MTU, u_int32_t, siap->xClaspec_composed_MTU); } #else Set_Break_Bit(shp); /* We do not support CONTROLLED LOAD */ #endif } Set_Serv_Hdr(shp, CONTROLLED_LOAD_SERV, cumlen); if (siap->xClaspec_flags & XASPEC_FLG_BRK) Set_Break_Bit(shp); shp = (IS_serv_hdr_t *)php; Set_Main_Hdr(mhp, (char *)shp - (char *)genp); return 0; } void hton_rapi_cmd(rapi_cmd_t *cmd) { } int api_addr_assign(api_addr *addr,const struct sockaddr *s) { switch (s->sa_family) { case AF_INET: addr->type = htons(API_ADDR_TYPE_IPv4); addr->port = ((struct sockaddr_in *) s)->sin_port; memcpy(&addr->u.addr_ipv4, &(((struct sockaddr_in *) s)->sin_addr), sizeof(addr->u.addr_ipv4)); return(TRUE); #ifdef USE_IPV6 case AF_INET6: addr->type = htons(API_ADDR_TYPE_IPv6); addr->port = ((struct sockaddr_in6 *) s)->sin6_port; memcpy(&addr->u.addr_ipv6, &(((struct sockaddr_in6 *) s)->sin6_addr), sizeof(addr->u.addr_ipv6)); return(TRUE); #endif /* USE_IPV6 */ default: return(FALSE); } } int sockaddr_assign(struct sockaddr *s,const api_addr *addr) { switch (ntohs(addr->type)) { case API_ADDR_TYPE_IPv4: s->sa_family = AF_INET; ((struct sockaddr_in *) s)->sin_port = addr->port; memcpy(&(((struct sockaddr_in *) s)->sin_addr), &addr->u.addr_ipv4, sizeof(addr->u.addr_ipv4)); return(TRUE); #ifdef USE_IPV6 case API_ADDR_TYPE_IPv6: s->sa_family = AF_INET6; ((struct sockaddr_in6 *) s)->sin6_port = addr->port; memcpy(&(((struct sockaddr_in6 *) s)->sin6_addr), &addr->u.addr_ipv6, sizeof(addr->u.addr_ipv6)); return(TRUE); #endif /* USE_IPV6 */ default: return(FALSE); } }