Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / atm / scspd / scsp_config.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_config.c,v 1.3 1999/08/28 01:15:32 peter Exp $
27  *
28  */
29
30 /*
31  * Server Cache Synchronization Protocol (SCSP) Support
32  * ----------------------------------------------------
33  *
34  * Configuration file processing
35  *
36  */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <net/if.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>
50   
51 #include <errno.h>
52 #include <libatm.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <syslog.h>
57
58 #include "scsp_msg.h"
59 #include "scsp_if.h"
60 #include "scsp_var.h"
61
62 #ifndef lint
63 __RCSID("@(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_config.c,v 1.3 1999/08/28 01:15:32 peter Exp $");
64 #endif
65
66
67 extern int      yyparse __P((void));
68
69 /*
70  * Global variables
71  */
72 FILE            *cfg_file;
73 Scsp_server     *current_server;
74 Scsp_dcs        *current_dcs;
75
76
77 /*
78  * Process the configuration file
79  *
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.
84  *
85  * Arguments:
86  *      cfn     configuration file name
87  *
88  * Returns:
89  *      0       configuration read with no errors
90  *      else    error found in configuration file
91  *
92  */
93 int
94 scsp_config(cfn)
95         char    *cfn;
96 {
97         int             rc;
98         Scsp_server     *ssp, *snext;
99
100         /*
101          * Open the configuration file
102          */
103         cfg_file = fopen(cfn, "r");
104         if (!cfg_file) {
105                 scsp_log(LOG_ERR, "can't open config file %s",
106                                 (void *)cfn);
107                 exit(1);
108         }
109
110         /*
111          * Initialize current interface pointer
112          */
113         current_server = (Scsp_server *)0;
114
115         /*
116          * Clear marks on any existing servers
117          */
118         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
119                 ssp->ss_mark = 0;
120         }
121
122         /*
123          * Scan the configuration file, processing each line as
124          * it is read
125          */
126         rc = yyparse();
127
128         /*
129          * Close the configuration file
130          */
131         fclose(cfg_file);
132
133         /*
134          * Delete any server entries that weren't updated
135          */
136         for (ssp = scsp_server_head; ssp; ssp = snext) {
137                 snext = ssp->ss_next;
138                 if (!ssp->ss_mark)
139                         scsp_server_delete(ssp);
140         }
141
142         return(rc);
143 }
144
145
146 /*
147  * Prepare for SCSP DCS setup
148  *
149  * This routine is called from yyparse() when a DCS command is found.
150  *
151  * Arguments:
152  *      none
153  *
154  * Returns:
155  *      0       success
156  *      1       error encountered
157  *
158  */
159 int
160 start_dcs()
161 {
162         Scsp_dcs                *dcsp;
163
164         /*
165          * Make sure we have a current server block
166          */
167         if (!current_server) {
168                 parse_error("server not found");
169                 return(1);
170         }
171
172         /*
173          * Allocate a DCS block
174          */
175         dcsp = (Scsp_dcs *)UM_ALLOC(sizeof(Scsp_dcs));
176         if (!dcsp) {
177                 scsp_mem_err("start_dcs: sizeof(Scsp_dcs)");
178         }
179         UM_ZERO(dcsp, sizeof(Scsp_dcs));
180
181         /*
182          * Fill out DCS links and default values
183          */
184         dcsp->sd_server = current_server;
185         dcsp->sd_addr.address_format = T_ATM_ABSENT;
186         dcsp->sd_subaddr.address_format = T_ATM_ABSENT;
187         dcsp->sd_sock = -1;
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);
194
195         current_dcs = dcsp;
196         return(0);
197 }
198
199
200 /*
201  * Finish up server configuration
202  *
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
205  * up the DCS block.
206  *
207  * Arguments:
208  *      none
209  *
210  * Returns:
211  *      0       success
212  *      1       error encountered
213  *
214  */
215 int
216 finish_dcs()
217 {
218         int             rc = 0;
219         Scsp_dcs        *dcsp;
220         Scsp_server     *ssp;
221
222         /*
223          * Make sure we have a current server block and DCS block
224          */
225         if (!current_server) {
226                 parse_error("server not found");
227                 return(1);
228         }
229
230         if (!current_dcs) {
231                 parse_error("server not found");
232                 return(1);
233         }
234         ssp = current_server;
235         dcsp = current_dcs;
236
237         /*
238          * Make sure the DCS ID is set
239          */
240         if (dcsp->sd_dcsid.id_len == 0) {
241                 parse_error("DCS ID not set");
242                 rc++;
243         }
244
245         /*
246          * Make sure the ATM address is set
247          */
248         if (dcsp->sd_addr.address_format == T_ATM_ABSENT) {
249                 parse_error("DCS ATM address not set");
250                 rc++;
251         }
252
253         current_dcs = (Scsp_dcs *)0;
254         return(rc);
255 }
256
257
258 /*
259  * Configure DCS ATM address
260  *
261  * This routine is called from yyparse() to process an ATMaddr command.
262  *
263  * Arguments:
264  *      ap      pointer to DCS's ATM address (in ASCII)
265  *      sap     pointer to DCS's ATM subaddress (in ASCII)
266  *
267  * Returns:
268  *      0       success
269  *      1       error encountered
270  *
271  */
272 int
273 set_dcs_addr(ap, sap)
274         char    *ap, *sap;
275 {
276         Scsp_dcs                *dcsp;
277         Atm_addr                addr, subaddr;
278
279         /*
280          * Make sure we have a current server block and DCS block
281          */
282         if (!current_server) {
283                 parse_error("server not found");
284                 return(1);
285         }
286
287         if (!current_dcs) {
288                 parse_error("server not found");
289                 return(1);
290         }
291         dcsp = current_dcs;
292
293         /*
294          * Initialize
295          */
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;
300
301         /*
302          * Convert the ATM address from character to internal format
303          */
304         if (ap) {
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");
309                         return(1);
310                 }
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;
316                 } else {
317                         parse_error("invalid ATM address");
318                         return(1);
319                 }
320         }
321
322         /*
323          * Convert the ATM subaddress from character to internal format
324          */
325         if (sap) {
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");
330                         return(1);
331                 }
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;
337                 } else {
338                         parse_error("invalid ATM subaddress");
339                         return(1);
340                 }
341         }
342
343         /*
344          * Make sure we have a legal ATM address type combination
345          */
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");
351                 return(1);
352         }
353
354         /*
355          * Save the address and subaddress
356          */
357         ATM_ADDR_COPY(&addr, &dcsp->sd_addr);
358         ATM_ADDR_COPY(&subaddr, &dcsp->sd_subaddr);
359
360         return(0);
361 }
362
363
364 /*
365  * Configure CA retransmit interval for DCS
366  *
367  * This routine is called from yyparse() to process a CAReXmitInt
368  * command.
369  *
370  * Arguments:
371  *      val     time interval
372  *
373  * Returns:
374  *      0       success
375  *      1       error encountered
376  *
377  */
378 int
379 set_dcs_ca_rexmit(val)
380         int     val;
381 {
382         Scsp_dcs        *dcsp;
383
384         /*
385          * Make sure we have a current server block and DCS block
386          */
387         if (!current_server) {
388                 parse_error("server not found");
389                 return(1);
390         }
391
392         if (!current_dcs) {
393                 parse_error("server not found");
394                 return(1);
395         }
396         dcsp = current_dcs;
397
398
399         /*
400          * Validate the interval
401          */
402         if (val <= 0 || val > 1024) {
403                 parse_error("invalid CA retransmit interval");
404                 return(1);
405         }
406
407         /*
408          * Set CA retransmit interval
409          */
410         dcsp->sd_ca_rexmt_int = val;
411
412         return(0);
413 }
414
415
416 /*
417  * Configure CSUS retransmit interval for DCS
418  *
419  * This routine is called from yyparse() to process a CSUSReXmitInt
420  * command.
421  *
422  * Arguments:
423  *      val     time interval
424  *
425  * Returns:
426  *      0       success
427  *      1       error encountered
428  *
429  */
430 int
431 set_dcs_csus_rexmit(val)
432         int     val;
433 {
434         Scsp_dcs        *dcsp;
435
436         /*
437          * Make sure we have a current server block and DCS block
438          */
439         if (!current_server) {
440                 parse_error("server not found");
441                 return(1);
442         }
443
444         if (!current_dcs) {
445                 parse_error("server not found");
446                 return(1);
447         }
448         dcsp = current_dcs;
449
450
451         /*
452          * Validate the interval
453          */
454         if (val <= 0 || val > 1024) {
455                 parse_error("invalid CSUS retransmit interval");
456                 return(1);
457         }
458
459         /*
460          * Set CSUS retransmit interval
461          */
462         dcsp->sd_csus_rexmt_int = val;
463
464         return(0);
465 }
466
467
468 /*
469  * Configure CSU retransmit interval for DCS
470  *
471  * This routine is called from yyparse() to process a CSUReXmitInt
472  * command.
473  *
474  * Arguments:
475  *      val     time interval
476  *
477  * Returns:
478  *      0       success
479  *      1       error encountered
480  *
481  */
482 int
483 set_dcs_csu_rexmit(val)
484         int     val;
485 {
486         Scsp_dcs        *dcsp;
487
488         /*
489          * Make sure we have a current server block and DCS block
490          */
491         if (!current_server) {
492                 parse_error("server not found");
493                 return(1);
494         }
495
496         if (!current_dcs) {
497                 parse_error("server not found");
498                 return(1);
499         }
500         dcsp = current_dcs;
501
502
503         /*
504          * Validate the interval
505          */
506         if (val <= 0 || val > 1024) {
507                 parse_error("invalid CSU retransmit interval");
508                 return(1);
509         }
510
511         /*
512          * Set CSU retransmit interval
513          */
514         dcsp->sd_csu_rexmt_int = val;
515
516         return(0);
517 }
518
519
520 /*
521  * Configure CSU retransmit limit for DCS
522  *
523  * This routine is called from yyparse() to process a CSUReXmitMax
524  * command.
525  *
526  * Arguments:
527  *      val     time interval
528  *
529  * Returns:
530  *      0       success
531  *      1       error encountered
532  *
533  */
534 int
535 set_dcs_csu_rexmit_max(val)
536         int     val;
537 {
538         Scsp_dcs        *dcsp;
539
540         /*
541          * Make sure we have a current server block and DCS block
542          */
543         if (!current_server) {
544                 parse_error("server not found");
545                 return(1);
546         }
547
548         if (!current_dcs) {
549                 parse_error("server not found");
550                 return(1);
551         }
552         dcsp = current_dcs;
553
554
555         /*
556          * Validate the interval
557          */
558         if (val <= 0 || val > 1024) {
559                 parse_error("invalid CSU retransmit maximum");
560                 return(1);
561         }
562
563         /*
564          * Set CSU retransmit limit
565          */
566         dcsp->sd_csu_rexmt_max = val;
567
568         return(0);
569 }
570
571
572 /*
573  * Configure Hello dead factor for DCS
574  *
575  * This routine is called from yyparse() to process a HelloDead
576  * command.
577  *
578  * Arguments:
579  *      val     number of times Hello interval has to expire before
580  *              a DCS is considered dead
581  *
582  * Returns:
583  *      0       success
584  *      1       error encountered
585  *
586  */
587 int
588 set_dcs_hello_df(val)
589         int     val;
590 {
591         Scsp_dcs        *dcsp;
592
593         /*
594          * Make sure we have a current server block and DCS block
595          */
596         if (!current_server) {
597                 parse_error("server not found");
598                 return(1);
599         }
600
601         if (!current_dcs) {
602                 parse_error("server not found");
603                 return(1);
604         }
605         dcsp = current_dcs;
606
607
608         /*
609          * Validate the limit
610          */
611         if (val <= 0 || val > 1024) {
612                 parse_error("invalid Hello dead factor");
613                 return(1);
614         }
615
616         /*
617          * Set Hello dead factor
618          */
619         dcsp->sd_hello_df = val;
620
621         return(0);
622 }
623
624
625 /*
626  * Configure Hello interval for DCS
627  *
628  * This routine is called from yyparse() to process a HelloInt
629  * command.
630  *
631  * Arguments:
632  *      val     time interval
633  *
634  * Returns:
635  *      0       success
636  *      1       error encountered
637  *
638  */
639 int
640 set_dcs_hello_int(val)
641         int     val;
642 {
643         Scsp_dcs        *dcsp;
644
645         /*
646          * Make sure we have a current server block and DCS block
647          */
648         if (!current_server) {
649                 parse_error("server not found");
650                 return(1);
651         }
652
653         if (!current_dcs) {
654                 parse_error("server not found");
655                 return(1);
656         }
657         dcsp = current_dcs;
658
659
660         /*
661          * Validate the interval
662          */
663         if (val <= 0 || val > 1024) {
664                 parse_error("invalid Hello interval");
665                 return(1);
666         }
667
668         /*
669          * Set Hello interval
670          */
671         dcsp->sd_hello_int = val;
672
673         return(0);
674 }
675
676
677 /*
678  * Configure hop count for SCSP server
679  *
680  * This routine is called from yyparse() to process a Hops command.
681  *
682  * Arguments:
683  *      hops    number of hops
684  *
685  * Returns:
686  *      0       success
687  *      1       error encountered
688  *
689  */
690 int
691 set_dcs_hops(hops)
692         int     hops;
693 {
694         Scsp_dcs        *dcsp;
695
696         /*
697          * Make sure we have a current server block and DCS block
698          */
699         if (!current_server) {
700                 parse_error("server not found");
701                 return(1);
702         }
703
704         if (!current_dcs) {
705                 parse_error("server not found");
706                 return(1);
707         }
708         dcsp = current_dcs;
709
710
711         /*
712          * Validate the count
713          */
714         if (hops <= 0 || hops > 1024) {
715                 parse_error("invalid hop count");
716                 return(1);
717         }
718
719         /*
720          * Set hop count
721          */
722         dcsp->sd_hops = hops;
723
724         return(0);
725 }
726
727
728 /*
729  * Configure DCS ID
730  *
731  * This routine is called from yyparse() to process an ID command.
732  *
733  * Arguments:
734  *      name    pointer to DCS's DNS name or IP address (in ASCII)
735  *
736  * Returns:
737  *      0       success
738  *      1       error encountered
739  *
740  */
741 int
742 set_dcs_id(name)
743         char    *name;
744 {
745         Scsp_dcs                *dcsp;
746         Scsp_server             *ssp;
747         struct sockaddr_in      *ip_addr;
748
749         /*
750          * Make sure we have a current server block and DCS block
751          */
752         if (!current_server) {
753                 parse_error("server not found");
754                 return(1);
755         }
756
757         if (!current_dcs) {
758                 parse_error("server not found");
759                 return(1);
760         }
761         ssp = current_server;
762         dcsp = current_dcs;
763
764         /*
765          * Convert the DNS name or IP address
766          */
767         ip_addr = get_ip_addr(name);
768         if (!ip_addr) {
769                 parse_error("invalid DCS IP address");
770                 return(1);
771         }
772
773         /*
774          * Verify the address length
775          */
776         if (ssp->ss_id_len != sizeof(ip_addr->sin_addr)) {
777                 parse_error("invalid DCS ID length");
778                 return(1);
779         }
780
781         /*
782          * Set the ID in the DCS block
783          */
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);
786
787         return(0);
788 }
789
790
791 /*
792  * Configure network interface for SCSP server
793  *
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
797  * control block.
798  *
799  * Arguments:
800  *      netif   pointer to network interface name
801  *
802  * Returns:
803  *      0       success
804  *      1       error encountered
805  *
806  */
807 int
808 set_intf(netif)
809         char    *netif;
810 {
811         int                     rc;
812         Scsp_server             *ssp;
813
814         /*
815          * Get the current network interface address
816          */
817         ssp = current_server;
818         if (!ssp) {
819                 parse_error("Server not found");
820                 rc = 1;
821                 goto set_intf_done;
822         }
823
824         /*
825          * Make sure we're configuring a valid
826          * network interface
827          */
828         rc = verify_nif_name(netif);
829         if (rc == 0) {
830                 parse_error("%s is not a valid network interface",
831                                 (void *)netif);
832                 rc = 1;
833                 goto set_intf_done;
834         } else if (rc < 0) {
835                 scsp_log(LOG_ERR, "Netif name verify error");
836                 exit(1);
837         }
838
839         /*
840          * Save the server's network interface name
841          */
842         strcpy(ssp->ss_intf, netif);
843         rc = 0;
844
845 set_intf_done:
846         return(rc);
847 }
848
849
850 /*
851  * Configure protocol for SCSP server
852  *
853  * This routine is called from yyparse() to process a Protocol command.
854  *
855  * Arguments:
856  *      proto   SCSP protocol being configured
857  *
858  * Returns:
859  *      0       success
860  *      1       error encountered
861  *
862  */
863 int
864 set_protocol(proto)
865         int     proto;
866 {
867         Scsp_server     *ssp;
868
869         /*
870          * Get address of current server block
871          */
872         ssp = current_server;
873         if (!ssp) {
874                 parse_error("server not found");
875                 return(1);
876         }
877
878         /*
879          * Process based on protocol ID
880          */
881         switch(proto) {
882         case SCSP_PROTO_ATMARP:
883                 ssp->ss_pid = proto;
884                 ssp->ss_id_len = SCSP_ATMARP_ID_LEN;
885                 ssp->ss_ckey_len = SCSP_ATMARP_KEY_LEN;
886                 break;
887         case SCSP_PROTO_NHRP:
888                 ssp->ss_pid = proto;
889                 ssp->ss_id_len = SCSP_NHRP_ID_LEN;
890                 ssp->ss_ckey_len = SCSP_NHRP_KEY_LEN;
891                 break;
892         case SCSP_PROTO_MARS:
893         case SCSP_PROTO_DHCP:
894         case SCSP_PROTO_LNNI:
895         default:
896                 parse_error("invalid protocol");
897                 return(1);
898         }
899
900         return(0);
901 }
902
903
904 /*
905  * Configure server group for SCSP server
906  *
907  * This routine is called from yyparse() to process a ServerGroupID
908  * command.
909  *
910  * Arguments:
911  *      sgid    server group id
912  *
913  * Returns:
914  *      0       success
915  *      1       error encountered
916  *
917  */
918 int
919 set_server_group(sgid)
920         int     sgid;
921 {
922         Scsp_server     *ssp;
923
924         /*
925          * Get address of current server block
926          */
927         ssp = current_server;
928         if (!ssp) {
929                 parse_error("server not found");
930                 return(1);
931         }
932
933         /*
934          * Validate server group ID
935          */
936         if (sgid <= 0) {
937                 parse_error("invalid server group ID");
938                 return(1);
939         }
940
941         /*
942          * Save the ID
943          */
944         ssp->ss_sgid = sgid;
945
946         return(0);
947 }
948
949
950 /*
951  * Prepare for SCSP server setup
952  *
953  * This routine is called from yyparse() when a Server statment is
954  * found.
955  *
956  * Arguments:
957  *      name    pointer to LIS name
958  *
959  * Returns:
960  *      0       success
961  *      else    error encountered
962  *
963  */
964 int
965 start_server(name)
966         char    *name;
967 {
968         int             i;
969         Scsp_server     *ssp;
970         Scsp_dcs        *dcsp, *next_dcs;
971         Scsp_cse        *csep, *next_cse;
972
973         /*
974          * See if we already have an entry for this name
975          */
976         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
977                 if (strcasecmp(ssp->ss_name, name) == 0)
978                         break;
979         }
980
981         if (ssp) {
982                 /*
983                  * Log the fact that we're updating the entry
984                  */
985                 scsp_log(LOG_INFO, "updating server entry for %s",
986                                 (void *)name);
987
988                 /*
989                  * Free the existing cache
990                  */
991                 for (i = 0; i < SCSP_HASHSZ; i++) {
992                         for (csep = ssp->ss_cache[i]; csep;
993                                         csep = next_cse) {
994                                 next_cse = csep->sc_next;
995                                 UNLINK(csep, Scsp_cse, ssp->ss_cache[i],
996                                                 sc_next);
997                                 UM_FREE(csep);
998                         }
999                 }
1000
1001                 /*
1002                  * Delete existing DCS blocks
1003                  */
1004                 for (dcsp = ssp->ss_dcs; dcsp; dcsp = next_dcs) {
1005                         next_dcs = dcsp->sd_next;
1006                         scsp_dcs_delete(dcsp);
1007                 }
1008         } else {
1009                 /*
1010                  * Get a new server entry
1011                  */
1012                 ssp = (Scsp_server *)UM_ALLOC(sizeof(Scsp_server));
1013                 if (!ssp) {
1014                         scsp_log(LOG_ERR, "unable to allocate server entry");
1015                         exit(1);
1016                 }
1017                 UM_ZERO(ssp, sizeof(Scsp_server));
1018                 ssp->ss_sock = -1;
1019                 ssp->ss_dcs_lsock = -1;
1020
1021                 /*
1022                  * Set the name
1023                  */
1024                 ssp->ss_name = strdup(name);
1025
1026                 /*
1027                  * Link in the new interface entry
1028                  */
1029                 LINK2TAIL(ssp, Scsp_server, scsp_server_head,
1030                                 ss_next);
1031         }
1032
1033         /*
1034          * If the mark is already set, this is a duplicate command
1035          */
1036         if (ssp->ss_mark) {
1037                 parse_error("duplicate server \"%s\"", name);
1038                 return(1);
1039         }
1040
1041         /*
1042          * Make this the current interface
1043          */
1044         current_server = ssp;
1045
1046         return(0);
1047 }
1048
1049
1050 /*
1051  * Finish up server configuration
1052  *
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.
1056  *
1057  * Arguments:
1058  *      None
1059  *
1060  * Returns:
1061  *      0       OK
1062  *      1       Error
1063  *
1064  */
1065 int
1066 finish_server()
1067 {
1068         int             rc = 0;
1069         Scsp_server     *ssp;
1070
1071         /*
1072          * Get the current network interface address
1073          */
1074         ssp = current_server;
1075         if (!ssp) {
1076                 parse_error("Server not found");
1077                 rc++;
1078         }
1079
1080         /*
1081          * Mark the interface as processed
1082          */
1083         ssp->ss_mark = 1;
1084
1085         /*
1086          * Make sure the interface has been configured
1087          */
1088         if (ssp->ss_intf == (char *)0) {
1089                 parse_error("netif missing from server specification");
1090                 rc++;
1091         }
1092
1093         /*
1094          * Make sure the protocol is set
1095          */
1096         if (ssp->ss_pid == 0) {
1097                 parse_error("protocol missing from server specification");
1098                 rc++;
1099         }
1100
1101         /*
1102          * Make sure the server group is set
1103          */
1104         if (ssp->ss_sgid == 0) {
1105                 parse_error("server group ID missing from server specification");
1106                 rc++;
1107         }
1108
1109         /*
1110          * Make sure at least one DCS is configured
1111          */
1112         if (ssp->ss_dcs == (Scsp_dcs *)0) {
1113                 parse_error("no DCS configured for server");
1114                 rc++;
1115         }
1116
1117         /*
1118          * Mark the end of the server
1119          */
1120         current_server = (Scsp_server *)0;
1121
1122         return(rc);
1123 }
1124
1125
1126 /*
1127  * Configure log file for SCSP server
1128  *
1129  * This routine is called from yyparse() to process a log File command.
1130  *
1131  * Arguments:
1132  *      file    name of logging file
1133  *
1134  * Returns:
1135  *      0       success
1136  *      1       error encountered
1137  *
1138  */
1139 int
1140 set_log_file(file)
1141         char    *file;
1142 {
1143         /*
1144          * Make sure we haven't already got a log file
1145          */
1146         if (scsp_log_file) {
1147                 parse_error("multiple log files specified");
1148                 return(1);
1149         }
1150
1151         /*
1152          * Open the file
1153          */
1154         scsp_log_file = fopen(file, "a");
1155         if (!scsp_log_file) {
1156                 parse_error("can't open log file");
1157                 return(1);
1158         }
1159
1160         return(0);
1161 }