📄 rapi_lib.c
字号:
return(rapi_dispatch_fd(rsvp_socket)); return RAPI_ERR_OK;}intrapi_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. */intrapi_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_trapi_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. */rapi_sid_tcommon_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; } 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. */intGet_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 voidsig_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 intinit_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);}staticstruct 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);}staticintconnect_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);}staticintconnect_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);}staticintconnect_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 intsend_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 SOLARISretry: #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);}intrapi_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -