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(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 = calloc(1, sizeof(Scsp_dcs));
177 scsp_mem_err("start_dcs: sizeof(Scsp_dcs)");
180 * Fill out DCS links and default values
182 dcsp->sd_server = current_server;
183 dcsp->sd_addr.address_format = T_ATM_ABSENT;
184 dcsp->sd_subaddr.address_format = T_ATM_ABSENT;
186 dcsp->sd_ca_rexmt_int = SCSP_CAReXmitInterval;
187 dcsp->sd_csus_rexmt_int = SCSP_CSUSReXmitInterval;
188 dcsp->sd_hops = SCSP_CSA_HOP_CNT;
189 dcsp->sd_csu_rexmt_int = SCSP_CSUReXmitInterval;
190 dcsp->sd_csu_rexmt_max = SCSP_CSUReXmitMax;
191 LINK2TAIL(dcsp, Scsp_dcs, current_server->ss_dcs, sd_next);
199 * Finish up server configuration
201 * This routine is called from yyparse() to at the end of a DCS
202 * command. It checks that required fields are set and finishes
210 * 1 error encountered
221 * Make sure we have a current server block and DCS block
223 if (!current_server) {
224 parse_error("server not found");
229 parse_error("server not found");
232 ssp = current_server;
236 * Make sure the DCS ID is set
238 if (dcsp->sd_dcsid.id_len == 0) {
239 parse_error("DCS ID not set");
244 * Make sure the ATM address is set
246 if (dcsp->sd_addr.address_format == T_ATM_ABSENT) {
247 parse_error("DCS ATM address not set");
251 current_dcs = (Scsp_dcs *)0;
257 * Configure DCS ATM address
259 * This routine is called from yyparse() to process an ATMaddr command.
262 * ap pointer to DCS's ATM address (in ASCII)
263 * sap pointer to DCS's ATM subaddress (in ASCII)
267 * 1 error encountered
271 set_dcs_addr(ap, sap)
275 Atm_addr addr, subaddr;
278 * Make sure we have a current server block and DCS block
280 if (!current_server) {
281 parse_error("server not found");
286 parse_error("server not found");
294 bzero(&addr, sizeof(addr));
295 addr.address_format = T_ATM_ABSENT;
296 bzero(&subaddr, sizeof(subaddr));
297 subaddr.address_format = T_ATM_ABSENT;
300 * Convert the ATM address from character to internal format
303 addr.address_length = get_hex_atm_addr(ap,
304 (u_char *)addr.address, strlen(ap));
305 if (addr.address_length == 0) {
306 parse_error("invalid ATM address");
309 if (addr.address_length == sizeof(Atm_addr_nsap)) {
310 addr.address_format = T_ATM_ENDSYS_ADDR;
311 } else if (addr.address_length <=
312 sizeof(Atm_addr_e164)) {
313 addr.address_format = T_ATM_E164_ADDR;
315 parse_error("invalid ATM address");
321 * Convert the ATM subaddress from character to internal format
324 subaddr.address_length = get_hex_atm_addr(sap,
325 (u_char *)subaddr.address, strlen(sap));
326 if (subaddr.address_length == 0) {
327 parse_error("invalid ATM address");
330 if (subaddr.address_length == sizeof(Atm_addr_nsap)) {
331 subaddr.address_format = T_ATM_ENDSYS_ADDR;
332 } else if (subaddr.address_length <=
333 sizeof(Atm_addr_e164)) {
334 subaddr.address_format = T_ATM_E164_ADDR;
336 parse_error("invalid ATM subaddress");
342 * Make sure we have a legal ATM address type combination
344 if (((addr.address_format != T_ATM_ENDSYS_ADDR) ||
345 (subaddr.address_format != T_ATM_ABSENT)) &&
346 ((addr.address_format != T_ATM_E164_ADDR) ||
347 (subaddr.address_format != T_ATM_ENDSYS_ADDR))) {
348 parse_error("invalid address/subaddress combination");
353 * Save the address and subaddress
355 ATM_ADDR_COPY(&addr, &dcsp->sd_addr);
356 ATM_ADDR_COPY(&subaddr, &dcsp->sd_subaddr);
363 * Configure CA retransmit interval for DCS
365 * This routine is called from yyparse() to process a CAReXmitInt
373 * 1 error encountered
377 set_dcs_ca_rexmit(val)
383 * Make sure we have a current server block and DCS block
385 if (!current_server) {
386 parse_error("server not found");
391 parse_error("server not found");
398 * Validate the interval
400 if (val <= 0 || val > 1024) {
401 parse_error("invalid CA retransmit interval");
406 * Set CA retransmit interval
408 dcsp->sd_ca_rexmt_int = val;
415 * Configure CSUS retransmit interval for DCS
417 * This routine is called from yyparse() to process a CSUSReXmitInt
425 * 1 error encountered
429 set_dcs_csus_rexmit(val)
435 * Make sure we have a current server block and DCS block
437 if (!current_server) {
438 parse_error("server not found");
443 parse_error("server not found");
450 * Validate the interval
452 if (val <= 0 || val > 1024) {
453 parse_error("invalid CSUS retransmit interval");
458 * Set CSUS retransmit interval
460 dcsp->sd_csus_rexmt_int = val;
467 * Configure CSU retransmit interval for DCS
469 * This routine is called from yyparse() to process a CSUReXmitInt
477 * 1 error encountered
481 set_dcs_csu_rexmit(val)
487 * Make sure we have a current server block and DCS block
489 if (!current_server) {
490 parse_error("server not found");
495 parse_error("server not found");
502 * Validate the interval
504 if (val <= 0 || val > 1024) {
505 parse_error("invalid CSU retransmit interval");
510 * Set CSU retransmit interval
512 dcsp->sd_csu_rexmt_int = val;
519 * Configure CSU retransmit limit for DCS
521 * This routine is called from yyparse() to process a CSUReXmitMax
529 * 1 error encountered
533 set_dcs_csu_rexmit_max(val)
539 * Make sure we have a current server block and DCS block
541 if (!current_server) {
542 parse_error("server not found");
547 parse_error("server not found");
554 * Validate the interval
556 if (val <= 0 || val > 1024) {
557 parse_error("invalid CSU retransmit maximum");
562 * Set CSU retransmit limit
564 dcsp->sd_csu_rexmt_max = val;
571 * Configure Hello dead factor for DCS
573 * This routine is called from yyparse() to process a HelloDead
577 * val number of times Hello interval has to expire before
578 * a DCS is considered dead
582 * 1 error encountered
586 set_dcs_hello_df(val)
592 * Make sure we have a current server block and DCS block
594 if (!current_server) {
595 parse_error("server not found");
600 parse_error("server not found");
609 if (val <= 0 || val > 1024) {
610 parse_error("invalid Hello dead factor");
615 * Set Hello dead factor
617 dcsp->sd_hello_df = val;
624 * Configure Hello interval for DCS
626 * This routine is called from yyparse() to process a HelloInt
634 * 1 error encountered
638 set_dcs_hello_int(val)
644 * Make sure we have a current server block and DCS block
646 if (!current_server) {
647 parse_error("server not found");
652 parse_error("server not found");
659 * Validate the interval
661 if (val <= 0 || val > 1024) {
662 parse_error("invalid Hello interval");
669 dcsp->sd_hello_int = val;
676 * Configure hop count for SCSP server
678 * This routine is called from yyparse() to process a Hops command.
681 * hops number of hops
685 * 1 error encountered
695 * Make sure we have a current server block and DCS block
697 if (!current_server) {
698 parse_error("server not found");
703 parse_error("server not found");
712 if (hops <= 0 || hops > 1024) {
713 parse_error("invalid hop count");
720 dcsp->sd_hops = hops;
729 * This routine is called from yyparse() to process an ID command.
732 * name pointer to DCS's DNS name or IP address (in ASCII)
736 * 1 error encountered
745 struct sockaddr_in *ip_addr;
748 * Make sure we have a current server block and DCS block
750 if (!current_server) {
751 parse_error("server not found");
756 parse_error("server not found");
759 ssp = current_server;
763 * Convert the DNS name or IP address
765 ip_addr = get_ip_addr(name);
767 parse_error("invalid DCS IP address");
772 * Verify the address length
774 if (ssp->ss_id_len != sizeof(ip_addr->sin_addr)) {
775 parse_error("invalid DCS ID length");
780 * Set the ID in the DCS block
782 dcsp->sd_dcsid.id_len = ssp->ss_id_len;
783 bcopy(&ip_addr->sin_addr, dcsp->sd_dcsid.id, ssp->ss_id_len);
790 * Configure network interface for SCSP server
792 * This routine is called from yyparse() to process a Netif command.
793 * It verifies the network interface name, gets interface information
794 * from the kernel, and sets the appropriate fields in the server
798 * netif pointer to network interface name
802 * 1 error encountered
813 * Get the current network interface address
815 ssp = current_server;
817 parse_error("Server not found");
823 * Make sure we're configuring a valid
826 rc = verify_nif_name(netif);
828 parse_error("%s is not a valid network interface",
833 scsp_log(LOG_ERR, "Netif name verify error");
838 * Save the server's network interface name
840 strcpy(ssp->ss_intf, netif);
849 * Configure protocol for SCSP server
851 * This routine is called from yyparse() to process a Protocol command.
854 * proto SCSP protocol being configured
858 * 1 error encountered
868 * Get address of current server block
870 ssp = current_server;
872 parse_error("server not found");
877 * Process based on protocol ID
880 case SCSP_PROTO_ATMARP:
882 ssp->ss_id_len = SCSP_ATMARP_ID_LEN;
883 ssp->ss_ckey_len = SCSP_ATMARP_KEY_LEN;
885 case SCSP_PROTO_NHRP:
887 ssp->ss_id_len = SCSP_NHRP_ID_LEN;
888 ssp->ss_ckey_len = SCSP_NHRP_KEY_LEN;
890 case SCSP_PROTO_MARS:
891 case SCSP_PROTO_DHCP:
892 case SCSP_PROTO_LNNI:
894 parse_error("invalid protocol");
903 * Configure server group for SCSP server
905 * This routine is called from yyparse() to process a ServerGroupID
909 * sgid server group id
913 * 1 error encountered
917 set_server_group(sgid)
923 * Get address of current server block
925 ssp = current_server;
927 parse_error("server not found");
932 * Validate server group ID
935 parse_error("invalid server group ID");
949 * Prepare for SCSP server setup
951 * This routine is called from yyparse() when a Server statment is
955 * name pointer to LIS name
959 * else error encountered
968 Scsp_dcs *dcsp, *next_dcs;
969 Scsp_cse *csep, *next_cse;
972 * See if we already have an entry for this name
974 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
975 if (strcasecmp(ssp->ss_name, name) == 0)
981 * Log the fact that we're updating the entry
983 scsp_log(LOG_INFO, "updating server entry for %s",
987 * Free the existing cache
989 for (i = 0; i < SCSP_HASHSZ; i++) {
990 for (csep = ssp->ss_cache[i]; csep;
992 next_cse = csep->sc_next;
993 UNLINK(csep, Scsp_cse, ssp->ss_cache[i],
1000 * Delete existing DCS blocks
1002 for (dcsp = ssp->ss_dcs; dcsp; dcsp = next_dcs) {
1003 next_dcs = dcsp->sd_next;
1004 scsp_dcs_delete(dcsp);
1008 * Get a new server entry
1010 ssp = calloc(1, sizeof(Scsp_server));
1012 scsp_log(LOG_ERR, "unable to allocate server entry");
1016 ssp->ss_dcs_lsock = -1;
1021 ssp->ss_name = strdup(name);
1024 * Link in the new interface entry
1026 LINK2TAIL(ssp, Scsp_server, scsp_server_head,
1031 * If the mark is already set, this is a duplicate command
1034 parse_error("duplicate server \"%s\"", name);
1039 * Make this the current interface
1041 current_server = ssp;
1048 * Finish up server configuration
1050 * This routine is called from yyparse() when the end of a server
1051 * statement is reached. It checks that required fields are set
1052 * and marks the entry as processed.
1069 * Get the current network interface address
1071 ssp = current_server;
1073 parse_error("Server not found");
1078 * Mark the interface as processed
1083 * Make sure the interface has been configured
1085 if (ssp->ss_intf == (char *)0) {
1086 parse_error("netif missing from server specification");
1091 * Make sure the protocol is set
1093 if (ssp->ss_pid == 0) {
1094 parse_error("protocol missing from server specification");
1099 * Make sure the server group is set
1101 if (ssp->ss_sgid == 0) {
1102 parse_error("server group ID missing from server specification");
1107 * Make sure at least one DCS is configured
1109 if (ssp->ss_dcs == (Scsp_dcs *)0) {
1110 parse_error("no DCS configured for server");
1115 * Mark the end of the server
1117 current_server = (Scsp_server *)0;
1124 * Configure log file for SCSP server
1126 * This routine is called from yyparse() to process a log File command.
1129 * file name of logging file
1133 * 1 error encountered
1141 * Make sure we haven't already got a log file
1143 if (scsp_log_file) {
1144 parse_error("multiple log files specified");
1151 scsp_log_file = fopen(file, "a");
1152 if (!scsp_log_file) {
1153 parse_error("can't open log file");