📄 rsvp_main.c
字号:
static voidsigint_handler(int sig){ log(LOG_ERR, 0, "Exiting on signal %d\n", sig); final(); _exit(sig);}/* * init_rsvp(): Initialize rsvpd. Read the vif info from the * kernel, initialize the sockets, and start the timer. */static intinit_rsvp(void){ int i; extern STYLE Style_Obj; /* Zero out and initialize headers of some global objects */ Init_Object(&Style_Obj, STYLE, STYLE_CTYPE); FD_ZERO(&fds); /* Misc initializations */ memset(session_hash, 0, SESS_HASH_SIZE*sizeof(Session *)); memset(key_assoc_table, 0, KEY_TABLE_SIZE * sizeof(KEY_ASSOC)); Key_Assoc_Max = 0; /* * Initialize encapsulation group G* and ports Pu, Pu', and * set up encapsulation socket addr structure. */ if (inet_pton(AF_INET,RSVP_ENCAP_GROUP,&encap_group) != 1){ log(LOG_ERR, errno, "Encap grp addr", 0); return(-1); } encap_port = hton16((u_int16_t) RSVP_ENCAP_PORT); encap_portp = hton16((u_int16_t) RSVP_ENCAP_PORTP); NET_SET_ADDR3_UDP_IPv4(&encap_mc_addr,encap_group,encap_port)#ifdef USE_IPV6 if (inet_pton(AF_INET6,RSVP_ENCAP_GROUP6,&encap_group6) != 1){ log(LOG_ERR, errno, "Encap grp addr 6", 0); return(-1); } NET_SET_ADDR3_UDP_IPv6(&encap_mc_addr6,encap_group6,encap_port)#endif /* USE_IPV6 */ rsrr_interface_query(1);#ifdef USE_IPV6 if (FAILED(net_init(encap_port,encap_portp, &encap_group,&encap_group6,FALSE))) {#else /* USE_IPV6 */ if (FAILED(net_init(encap_port,encap_portp,&encap_group,FALSE))) {#endif /* USE_IPV6 */ log(LOG_ERR,errno,"net_init"); return(SYS_ERROR); } /* In case mrouted is slow */ rsrr_initial_reply = 1; rsrr_dispatch(); /* * Look for a configuration file and apply it. For interfaces * whose LL init routine is not specified in config file, set * default LL (pt-pt|LAN) */ read_config_file("rsvpd.conf"); for (i = 0; i < if_num; i++) { if (IsNumAPI(i)) continue; if (*if_vec[i].if_LLifv.LL_NewFlow_p == NULL) KernTC_if_init(i); /* default traffic control */ } print_ifs(); if (FAILED(net_poll_list(&fds))) { log(LOG_ERR,errno,"net_poll_list"); return(SYS_ERROR); } /* Initialize: * -- probe_socket: socket for receiving status probes * -- api_socket: API listen socket * -- Timer routines * -- kernel traffic control */ init_probe_socket(); init_api(); init_timer(MAX_TIMER_Q); return (0);}intstatus_probe(int ifd) { char recv_buf[MAX_PKT]; struct sockaddr_in from; int from_len, recv_len; from_len = sizeof(from); memset((char *) &from, 0, from_len); recv_len = recvfrom(ifd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *) & from, &from_len); if (recv_len < 0) { log(LOG_ERR, errno, "recvfrom", 0); return(-1); } send_rsvp_state(recv_buf, recv_len, &from); return(0);}/* * start_UDP_encap(vif_no): Called to initialize for UDP encapsulation * on specified vif number. */intstart_UDP_encap(int vif) { IF_FLAGS(vif) |= IF_FLAG_UseUDP; return(0);}#define Clear_LL_Vector(n) memset(&if_vec[n].if_LLifv, 0, sizeof(LLDAL_calls_t))/* * if_list_init(): * Initialize table describing physical interfaces, * if_vec[0...if_num]. Return number of interfaces if_num. * The last element corresponds to the API. */intif_list_init() { int if_num = 0; struct ifreq ifr; struct if_nameindex *p,*q; struct if_attributes *l; struct sockaddr *s; net_addr addr;#if DEBUG if (Test_mode) { /* Test mode: read file named .rsvp.ifs containing: * <if name> <if address> <remote addr> */ FILE *fp = fopen(".rsvp.ifs", "r"); char buff[80], ipaddrstr[64], ifname[32], rmtaddrstr[64]; if (fp == NULL) { fprintf(stderr, "Error reading .rsvpifs\n"); exit(1); } if_vec = (if_rec *) calloc(MAX_INTERFACES, sizeof(if_rec)); tsttun_vec = (net_addr *) calloc(RSRR_MAX_VIFS_V2+1, sizeof(net_addr)); tst_sock2if = (int *) calloc(256, sizeof(int)); memset(tst_sock2if, -1, 4*256); while (fgets(buff, sizeof(buff), fp)) { if (if_num >= (MAX_INTERFACES - 1)) { fprintf(stderr, ".rsvpifs file too big\n"); exit(1); } sscanf(buff, "%s %s %s", ifname, ipaddrstr, rmtaddrstr); if_vec[if_num].if_flags = 0; if_vec[if_num].if_index = if_num; if_vec[if_num].if_unicast = if_num; strncpy(if_vec[if_num].if_name, ifname, IFNAMSIZ); net_addr_ascii(&addr,ipaddrstr); NET_SET_IF_PHY(&if_vec[if_num].if_addr,addr,if_num); net_addr_ascii(&tsttun_vec[if_num],rmtaddrstr); if_num++; } strcpy(if_vec[if_num].if_name, "API"); if_vec[if_num].if_unicast = if_num; api_num = if_num; return(++if_num); }#endif p = if_nameindex(); if(p == NULL) return(0); if_vec = (if_rec *) calloc(MAX_INTERFACES, sizeof(if_rec)); for(q = p; q->if_name != NULL; q++) { if (strncmp("lo",q->if_name,2) == 0) continue; l = if_attributes(q->if_index); for(s = l->addr; s != NULL; s = (++l)->addr) { switch (s->sa_family) { case AF_INET: if (local_v4 == -1) if (l->flags&IFF_UP) local_v4 = if_num; break;#ifdef USE_IPV6 case AF_INET6: if (local_v6 == -1) if (l->flags&IFF_UP) local_v6 = if_num; break;#endif /* USE_IPV6 */ default: continue; } if (if_num == (MAX_INTERFACES - 1)) { log(LOG_ERR,0,"Too Many Network Interfaces"); break; } strncpy(if_vec[if_num].if_name, q->if_name, IFNAMSIZ); net_addr_assign(&addr,s); NET_SET_IF_PHY(&if_vec[if_num].if_addr,addr, q->if_index); if_vec[if_num].if_index = q->if_index; if_vec[if_num].if_unicast = if_num; strncpy(ifr.ifr_name,q->if_name,sizeof(ifr.ifr_name)); if_vec[if_num].if_flags = (l->flags&IFF_UP) ? IF_FLAG_IFF_UP : 0; if_vec[if_num].if_flags |= (l->flags&IFF_MULTICAST) ? IF_FLAG_IFF_MC : 0; if_vec[if_num].if_udpttl = RSVP_TTL_ENCAP; if_vec[if_num].prefix = l->prefix; Clear_LL_Vector(if_num); /* for safety */ if_num++; } } if_freenameindex(p); /* Add one more entry corresponding to API */ Clear_LL_Vector(if_num); /* No intserv link layer for API */ strcpy(if_vec[if_num].if_name, "API"); if_vec[if_num].if_unicast = if_num; if_vec[if_num].if_flags = IF_FLAG_IFF_UP; /* Well, yes */ if_vec[if_num].prefix = 0; NET_SET_IF_PHY(&if_vec[if_num].if_addr,api_address,0); api_num = if_num; return (++if_num);}/* * init_api() initializes the api between the daemon and client applications. * The daemon listens for incoming requests (coming on a unix socket) from * application, and stores some local info about these requests. This info * includes a copy of an RSVP packet with the needed info, that will be * refreshed and throughn in every refresh period. */voidinit_api(){ int i; struct sockaddr_un server; /* struct sockaddr_in myaddr; */ int addr_len; memset(api_table, 0, sizeof(api_table)); /* if ((api_udp_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { log(LOG_WARNING, errno, "opening api_udp_socket\n"); } else { myaddr.sin_family = htons(AF_INET); myaddr.sin_port = htons(API_PORT); myaddr.sin_addr.s_addr = 0; if (FAILED(bind(api_udp_socket,(struct sockaddr *)&myaddr, sizeof(myaddr)))) { log(LOG_WARNING, errno, "bind() for api_udp_socket\n"); } } */ (void) unlink(SNAME); /* The unix socket name */ if ((api_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { log(LOG_WARNING, errno, "opening socket\n"); assert(NULL); /* i.e. abort() */ } server.sun_family = AF_UNIX; (void) strcpy(server.sun_path, SNAME);#ifdef STANDARD_C_LIBRARY /* * This is only necessary for Net/2 and later, but it's never * incorrect on earlier systems, so do it. */ addr_len = (offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path));#else addr_len = sizeof(server.sun_family) + strlen(server.sun_path);#endif#ifdef SOCKADDR_LEN server.sun_len = addr_len;#endif if (bind(api_socket, (struct sockaddr *) & server, addr_len) < 0) { log(LOG_WARNING, errno, "bind"); assert(NULL); /* i.e. abort() */ } if (chmod(SNAME,SMODE) == -1) log(LOG_WARNING, errno, "chmod of API socket"); i = 1;#ifdef SOLARIS if (fcntl(api_socket, F_SETFL, (fcntl(api_socket, F_GETFL) | O_NONBLOCK)) == -1) { log(LOG_ERR, errno, "Setting Non-blocking I/O\n"); exit(-1); }#else if (ioctl(api_socket, FIONBIO, &i) == -1) { log(LOG_ERR, errno, "Setting Non-blocking I/O\n"); exit(-1); }#endif /* SOLARIS */ (void) listen(api_socket, 10); /* Maximum pending req. at one time */}/* * api_input(): reads an API request from UNIX pipe, and processes it. * First 4 bytes are length of following request. */intapi_input(int fd) { int rc, len, nr; int sid; char recv_buf[MAX_MSG]; rsvp_req *req = (rsvp_req *) recv_buf; int ret_val = 0; /* if (fd == api_udp_socket) rc = recvfrom(fd,recv_buf,sizeof(recv_buf),0,NULL,NULL); else { */ rc = read(fd, &len, sizeof(int));#ifdef USE_NET_BO NTOH32(len);#endif if (rc != sizeof(int)) { if (rc == 0) { /* * Application quit or died rather than closed * the RSVP connection; not an error. */ ret_val = 0; goto err_exit; } else { log(LOG_ERR, errno, "Error in API read\n"); ret_val = -1; goto err_exit; } } nr = len; while (nr) { rc = read(fd, (char *) req, nr); if (rc <= 0) { ret_val = RAPI_ERR_NORSVP; goto err_exit; } nr -= rc; } /* } */ if (req->rq_type == API_DEBUG) { char *cmd = (char *)req + sizeof(rsvp_req); ntoh_rapi_cmd((rapi_cmd_t *)cmd); return(api_cmd(fd, (rapi_cmd_t *)cmd)); } else if (req->rq_type == API2_STAT) /* Trigger event upcalls to return status */ return(api_status(req)); /* if (NetByteOrderReq(req) || fd == api_udp_socket) */ if (NetByteOrderReq(req)) ntoh_api_request(req, rc); /* Convert to host byte order */ /* Locate or create local sid for this request, given the * fd (Unix pipe) on which it arrived, the process from which * it came, and client's sid. */ sid = find_sid(fd, req->rq_pid, req->rq_a_sid); if (sid < 0 && req->rq_type == API2_REGISTER) { /* First message; look for available slot. */ sid = find_free_sid(fd, req->rq_pid, req->rq_a_sid); if (sid < 0) { /* XXX api error */ log(LOG_WARNING, 0, "API: too many sessions\n"); return (-1); } memset(&api_table[sid], 0, sizeof(api_rec)); api_table[sid].api_fd = fd; api_table[sid].api_pid = req->rq_pid; api_table[sid].api_a_sid = req->rq_a_sid; num_sessions++; } else if (sid < 0) { log(LOG_ERR, 0, "API: req %d from ?? pid= %dAsid= %d\n", req->rq_type, req->rq_pid, req->rq_a_sid); return(-1); } if (process_api_req(sid, req, rc) < 0) { /* Return code = -1 => release the session. */ api_table[sid].api_fd = 0; rsvp_api_close(sid); if (req->rq_type != API_CLOSE) { /* Even though only one session had error, * close the Unix socket to the process. */ (void) close(fd); FD_CLR(fd, &fds); return(-1); } } return(0);err_exit: /* No message from which to derive the SID, but we * have to close all sids that used that fd. */ for (sid = 0; sid < API_TABLE_SIZE; sid++) { if (api_table[sid].api_fd == fd) { api_table[sid].api_fd = 0; /* prevent upcall */ process_api_req(sid, NULL, 0); rsvp_api_close(sid); } } /* Now close the socket. */ FD_CLR(fd, &fds); (void) close(fd); return ret_val; }intsid_hash(int fd, int pid, int client_sid) { u_int32_t ufd = fd; u_int32_t upid = pid; u_int32_t u_client_sid = client_sid; return ((((ufd*65599 + upid)*65599) + u_client_sid)*65599) % API_TABLE_SIZE; } /* * find_sid(): Search API table to locate sid for this fd, pid, and client_sid * * Use open hash table. Return -1 if no match. */intfind_sid(int fd, int pid, int client_sid) { int first_sid = sid_hash(fd, pid, client_sid); int test_sid, i; api_rec * test_rec; for (i=0, test_sid=first_sid; i<API_TABLE_SIZE; test_sid++, i++) { if (test_sid >= API_TABLE_SIZE) test_sid -= API_TABLE_SIZE; test_rec = &api_table[test_sid]; if (test_rec->api_fd == fd && test_rec->api_pid == pid && test_rec->api_a_sid == client_sid) return test_sid; else if (test_rec->api_fd == 0) return(-1); } return -1; /* no match */ } /* find_free_sid(): Returns sid for a free slot in API table api_table[], * for this fd, pid and client_sid. Does not allocate. */intfind_free_sid(int fd, int pid, int client_sid) { int first_sid = sid_hash(fd, pid, client_sid); int test_sid, i; api_rec * test_rec; /* do not allow hash table to get more than half full */ if (num_sessions >= MAX_SESSIONS) return -1; for (i=0, test_sid=first_sid; i<API_TABLE_SIZE; test_sid++, i++) { if (test_sid >= API_TABLE_SIZE) test_sid -= API_TABLE_SIZE; test_rec = &api_table[test_sid]; if (test_rec->api_fd == 0) return test_sid; } return -1; /* no match */ } /* * Release API session */voidrsvp_api_close(int sid) { api_rec *recp = &api_table[sid]; del_from_timer((char *) (unsigned long)sid, TIMEV_API); api_free_packet(&recp->api_p_packet); api_free_packet(&recp->api_r_packet); num_sessions--;}/* * refresh_api(): Called from process_api_req when new request * arrives from API, and periodically from timer. It injects * stored API packets into the processing as if they had arrived * from the network (except API packets are in host byte order). * * Returns 0 normally to restart timer, -1 to kill timer. */intrefresh_api(int sid) { api_rec *recp = &api_table[sid]; int rc; /* * Make sure the process still exists before keeping the message * alive. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -