3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
31 * Server Cache Synchronization Protocol (SCSP) Support
32 * ----------------------------------------------------
34 * Configuration file processing
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <netatm/port.h>
44 #include <netatm/queue.h>
45 #include <netatm/atm.h>
46 #include <netatm/atm_if.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_sys.h>
49 #include <netatm/atm_ioctl.h>
63 __RCSID("@(#) $FreeBSD$");
67 extern int yyparse __P((void));
73 Scsp_server *current_server;
74 Scsp_dcs *current_dcs;
78 * Process the configuration file
80 * This routine is called when the daemon starts, and it can also be
81 * called while it is running, as the result of a SIGHUP signal. It
82 * therefore has to be capable of both configuring the daemon from
83 * scratch and modifying the configuration of a running daemon.
86 * cfn configuration file name
89 * 0 configuration read with no errors
90 * else error found in configuration file
98 Scsp_server *ssp, *snext;
101 * Open the configuration file
103 cfg_file = fopen(cfn, "r");
105 scsp_log(LOG_ERR, "can't open config file %s",
111 * Initialize current interface pointer
113 current_server = (Scsp_server *)0;
116 * Clear marks on any existing servers
118 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
123 * Scan the configuration file, processing each line as
129 * Close the configuration file
134 * Delete any server entries that weren't updated
136 for (ssp = scsp_server_head; ssp; ssp = snext) {
137 snext = ssp->ss_next;
139 scsp_server_delete(ssp);
147 * Prepare for SCSP DCS setup
149 * This routine is called from yyparse() when a DCS command is found.
156 * 1 error encountered
165 * Make sure we have a current server block
167 if (!current_server) {
168 parse_error("server not found");
173 * Allocate a DCS block
175 dcsp = (Scsp_dcs *)UM_ALLOC(sizeof(Scsp_dcs));
177 scsp_mem_err("start_dcs: sizeof(Scsp_dcs)");
179 UM_ZERO(dcsp, sizeof(Scsp_dcs));
182 * Fill out DCS links and default values
184 dcsp->sd_server = current_server;
185 dcsp->sd_addr.address_format = T_ATM_ABSENT;
186 dcsp->sd_subaddr.address_format = T_ATM_ABSENT;
188 dcsp->sd_ca_rexmt_int = SCSP_CAReXmitInterval;
189 dcsp->sd_csus_rexmt_int = SCSP_CSUSReXmitInterval;
190 dcsp->sd_hops = SCSP_CSA_HOP_CNT;
191 dcsp->sd_csu_rexmt_int = SCSP_CSUReXmitInterval;
192 dcsp->sd_csu_rexmt_max = SCSP_CSUReXmitMax;
193 LINK2TAIL(dcsp, Scsp_dcs, current_server->ss_dcs, sd_next);
201 * Finish up server configuration
203 * This routine is called from yyparse() to at the end of a DCS
204 * command. It checks that required fields are set and finishes
212 * 1 error encountered
223 * Make sure we have a current server block and DCS block
225 if (!current_server) {
226 parse_error("server not found");
231 parse_error("server not found");
234 ssp = current_server;
238 * Make sure the DCS ID is set
240 if (dcsp->sd_dcsid.id_len == 0) {
241 parse_error("DCS ID not set");
246 * Make sure the ATM address is set
248 if (dcsp->sd_addr.address_format == T_ATM_ABSENT) {
249 parse_error("DCS ATM address not set");
253 current_dcs = (Scsp_dcs *)0;
259 * Configure DCS ATM address
261 * This routine is called from yyparse() to process an ATMaddr command.
264 * ap pointer to DCS's ATM address (in ASCII)
265 * sap pointer to DCS's ATM subaddress (in ASCII)
269 * 1 error encountered
273 set_dcs_addr(ap, sap)
277 Atm_addr addr, subaddr;
280 * Make sure we have a current server block and DCS block
282 if (!current_server) {
283 parse_error("server not found");
288 parse_error("server not found");
296 UM_ZERO(&addr, sizeof(addr));
297 addr.address_format = T_ATM_ABSENT;
298 UM_ZERO(&subaddr, sizeof(subaddr));
299 subaddr.address_format = T_ATM_ABSENT;
302 * Convert the ATM address from character to internal format
305 addr.address_length = get_hex_atm_addr(ap,
306 (u_char *)addr.address, strlen(ap));
307 if (addr.address_length == 0) {
308 parse_error("invalid ATM address");
311 if (addr.address_length == sizeof(Atm_addr_nsap)) {
312 addr.address_format = T_ATM_ENDSYS_ADDR;
313 } else if (addr.address_length <=
314 sizeof(Atm_addr_e164)) {
315 addr.address_format = T_ATM_E164_ADDR;
317 parse_error("invalid ATM address");
323 * Convert the ATM subaddress from character to internal format
326 subaddr.address_length = get_hex_atm_addr(sap,
327 (u_char *)subaddr.address, strlen(sap));
328 if (subaddr.address_length == 0) {
329 parse_error("invalid ATM address");
332 if (subaddr.address_length == sizeof(Atm_addr_nsap)) {
333 subaddr.address_format = T_ATM_ENDSYS_ADDR;
334 } else if (subaddr.address_length <=
335 sizeof(Atm_addr_e164)) {
336 subaddr.address_format = T_ATM_E164_ADDR;
338 parse_error("invalid ATM subaddress");
344 * Make sure we have a legal ATM address type combination
346 if (((addr.address_format != T_ATM_ENDSYS_ADDR) ||
347 (subaddr.address_format != T_ATM_ABSENT)) &&
348 ((addr.address_format != T_ATM_E164_ADDR) ||
349 (subaddr.address_format != T_ATM_ENDSYS_ADDR))) {
350 parse_error("invalid address/subaddress combination");
355 * Save the address and subaddress
357 ATM_ADDR_COPY(&addr, &dcsp->sd_addr);
358 ATM_ADDR_COPY(&subaddr, &dcsp->sd_subaddr);
365 * Configure CA retransmit interval for DCS
367 * This routine is called from yyparse() to process a CAReXmitInt
375 * 1 error encountered
379 set_dcs_ca_rexmit(val)
385 * Make sure we have a current server block and DCS block
387 if (!current_server) {
388 parse_error("server not found");
393 parse_error("server not found");
400 * Validate the interval
402 if (val <= 0 || val > 1024) {
403 parse_error("invalid CA retransmit interval");
408 * Set CA retransmit interval
410 dcsp->sd_ca_rexmt_int = val;
417 * Configure CSUS retransmit interval for DCS
419 * This routine is called from yyparse() to process a CSUSReXmitInt
427 * 1 error encountered
431 set_dcs_csus_rexmit(val)
437 * Make sure we have a current server block and DCS block
439 if (!current_server) {
440 parse_error("server not found");
445 parse_error("server not found");
452 * Validate the interval
454 if (val <= 0 || val > 1024) {
455 parse_error("invalid CSUS retransmit interval");
460 * Set CSUS retransmit interval
462 dcsp->sd_csus_rexmt_int = val;
469 * Configure CSU retransmit interval for DCS
471 * This routine is called from yyparse() to process a CSUReXmitInt
479 * 1 error encountered
483 set_dcs_csu_rexmit(val)
489 * Make sure we have a current server block and DCS block
491 if (!current_server) {
492 parse_error("server not found");
497 parse_error("server not found");
504 * Validate the interval
506 if (val <= 0 || val > 1024) {
507 parse_error("invalid CSU retransmit interval");
512 * Set CSU retransmit interval
514 dcsp->sd_csu_rexmt_int = val;
521 * Configure CSU retransmit limit for DCS
523 * This routine is called from yyparse() to process a CSUReXmitMax
531 * 1 error encountered
535 set_dcs_csu_rexmit_max(val)
541 * Make sure we have a current server block and DCS block
543 if (!current_server) {
544 parse_error("server not found");
549 parse_error("server not found");
556 * Validate the interval
558 if (val <= 0 || val > 1024) {
559 parse_error("invalid CSU retransmit maximum");
564 * Set CSU retransmit limit
566 dcsp->sd_csu_rexmt_max = val;
573 * Configure Hello dead factor for DCS
575 * This routine is called from yyparse() to process a HelloDead
579 * val number of times Hello interval has to expire before
580 * a DCS is considered dead
584 * 1 error encountered
588 set_dcs_hello_df(val)
594 * Make sure we have a current server block and DCS block
596 if (!current_server) {
597 parse_error("server not found");
602 parse_error("server not found");
611 if (val <= 0 || val > 1024) {
612 parse_error("invalid Hello dead factor");
617 * Set Hello dead factor
619 dcsp->sd_hello_df = val;
626 * Configure Hello interval for DCS
628 * This routine is called from yyparse() to process a HelloInt
636 * 1 error encountered
640 set_dcs_hello_int(val)
646 * Make sure we have a current server block and DCS block
648 if (!current_server) {
649 parse_error("server not found");
654 parse_error("server not found");
661 * Validate the interval
663 if (val <= 0 || val > 1024) {
664 parse_error("invalid Hello interval");
671 dcsp->sd_hello_int = val;
678 * Configure hop count for SCSP server
680 * This routine is called from yyparse() to process a Hops command.
683 * hops number of hops
687 * 1 error encountered
697 * Make sure we have a current server block and DCS block
699 if (!current_server) {
700 parse_error("server not found");
705 parse_error("server not found");
714 if (hops <= 0 || hops > 1024) {
715 parse_error("invalid hop count");
722 dcsp->sd_hops = hops;
731 * This routine is called from yyparse() to process an ID command.
734 * name pointer to DCS's DNS name or IP address (in ASCII)
738 * 1 error encountered
747 struct sockaddr_in *ip_addr;
750 * Make sure we have a current server block and DCS block
752 if (!current_server) {
753 parse_error("server not found");
758 parse_error("server not found");
761 ssp = current_server;
765 * Convert the DNS name or IP address
767 ip_addr = get_ip_addr(name);
769 parse_error("invalid DCS IP address");
774 * Verify the address length
776 if (ssp->ss_id_len != sizeof(ip_addr->sin_addr)) {
777 parse_error("invalid DCS ID length");
782 * Set the ID in the DCS block
784 dcsp->sd_dcsid.id_len = ssp->ss_id_len;
785 UM_COPY(&ip_addr->sin_addr, dcsp->sd_dcsid.id, ssp->ss_id_len);
792 * Configure network interface for SCSP server
794 * This routine is called from yyparse() to process a Netif command.
795 * It verifies the network interface name, gets interface information
796 * from the kernel, and sets the appropriate fields in the server
800 * netif pointer to network interface name
804 * 1 error encountered
815 * Get the current network interface address
817 ssp = current_server;
819 parse_error("Server not found");
825 * Make sure we're configuring a valid
828 rc = verify_nif_name(netif);
830 parse_error("%s is not a valid network interface",
835 scsp_log(LOG_ERR, "Netif name verify error");
840 * Save the server's network interface name
842 strcpy(ssp->ss_intf, netif);
851 * Configure protocol for SCSP server
853 * This routine is called from yyparse() to process a Protocol command.
856 * proto SCSP protocol being configured
860 * 1 error encountered
870 * Get address of current server block
872 ssp = current_server;
874 parse_error("server not found");
879 * Process based on protocol ID
882 case SCSP_PROTO_ATMARP:
884 ssp->ss_id_len = SCSP_ATMARP_ID_LEN;
885 ssp->ss_ckey_len = SCSP_ATMARP_KEY_LEN;
887 case SCSP_PROTO_NHRP:
889 ssp->ss_id_len = SCSP_NHRP_ID_LEN;
890 ssp->ss_ckey_len = SCSP_NHRP_KEY_LEN;
892 case SCSP_PROTO_MARS:
893 case SCSP_PROTO_DHCP:
894 case SCSP_PROTO_LNNI:
896 parse_error("invalid protocol");
905 * Configure server group for SCSP server
907 * This routine is called from yyparse() to process a ServerGroupID
911 * sgid server group id
915 * 1 error encountered
919 set_server_group(sgid)
925 * Get address of current server block
927 ssp = current_server;
929 parse_error("server not found");
934 * Validate server group ID
937 parse_error("invalid server group ID");
951 * Prepare for SCSP server setup
953 * This routine is called from yyparse() when a Server statment is
957 * name pointer to LIS name
961 * else error encountered
970 Scsp_dcs *dcsp, *next_dcs;
971 Scsp_cse *csep, *next_cse;
974 * See if we already have an entry for this name
976 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
977 if (strcasecmp(ssp->ss_name, name) == 0)
983 * Log the fact that we're updating the entry
985 scsp_log(LOG_INFO, "updating server entry for %s",
989 * Free the existing cache
991 for (i = 0; i < SCSP_HASHSZ; i++) {
992 for (csep = ssp->ss_cache[i]; csep;
994 next_cse = csep->sc_next;
995 UNLINK(csep, Scsp_cse, ssp->ss_cache[i],
1002 * Delete existing DCS blocks
1004 for (dcsp = ssp->ss_dcs; dcsp; dcsp = next_dcs) {
1005 next_dcs = dcsp->sd_next;
1006 scsp_dcs_delete(dcsp);
1010 * Get a new server entry
1012 ssp = (Scsp_server *)UM_ALLOC(sizeof(Scsp_server));
1014 scsp_log(LOG_ERR, "unable to allocate server entry");
1017 UM_ZERO(ssp, sizeof(Scsp_server));
1019 ssp->ss_dcs_lsock = -1;
1024 ssp->ss_name = strdup(name);
1027 * Link in the new interface entry
1029 LINK2TAIL(ssp, Scsp_server, scsp_server_head,
1034 * If the mark is already set, this is a duplicate command
1037 parse_error("duplicate server \"%s\"", name);
1042 * Make this the current interface
1044 current_server = ssp;
1051 * Finish up server configuration
1053 * This routine is called from yyparse() when the end of a server
1054 * statement is reached. It checks that required fields are set
1055 * and marks the entry as processed.
1072 * Get the current network interface address
1074 ssp = current_server;
1076 parse_error("Server not found");
1081 * Mark the interface as processed
1086 * Make sure the interface has been configured
1088 if (ssp->ss_intf == (char *)0) {
1089 parse_error("netif missing from server specification");
1094 * Make sure the protocol is set
1096 if (ssp->ss_pid == 0) {
1097 parse_error("protocol missing from server specification");
1102 * Make sure the server group is set
1104 if (ssp->ss_sgid == 0) {
1105 parse_error("server group ID missing from server specification");
1110 * Make sure at least one DCS is configured
1112 if (ssp->ss_dcs == (Scsp_dcs *)0) {
1113 parse_error("no DCS configured for server");
1118 * Mark the end of the server
1120 current_server = (Scsp_server *)0;
1127 * Configure log file for SCSP server
1129 * This routine is called from yyparse() to process a log File command.
1132 * file name of logging file
1136 * 1 error encountered
1144 * Make sure we haven't already got a log file
1146 if (scsp_log_file) {
1147 parse_error("multiple log files specified");
1154 scsp_log_file = fopen(file, "a");
1155 if (!scsp_log_file) {
1156 parse_error("can't open log file");