]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - usr.sbin/ctld/parse.y
MFC r274791:
[FreeBSD/stable/10.git] / usr.sbin / ctld / parse.y
1 %{
2 /*-
3  * Copyright (c) 2012 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * This software was developed by Edward Tomasz Napierala under sponsorship
7  * from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #include <sys/queue.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <assert.h>
37 #include <stdio.h>
38 #include <stdint.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include "ctld.h"
43
44 extern FILE *yyin;
45 extern char *yytext;
46 extern int lineno;
47
48 static struct conf *conf = NULL;
49 static struct auth_group *auth_group = NULL;
50 static struct portal_group *portal_group = NULL;
51 static struct target *target = NULL;
52 static struct lun *lun = NULL;
53
54 extern void     yyerror(const char *);
55 extern int      yylex(void);
56 extern void     yyrestart(FILE *);
57
58 %}
59
60 %token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
61 %token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP DISCOVERY_FILTER
62 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
63 %token LISTEN LISTEN_ISER LUN MAXPROC OPENING_BRACKET OPTION
64 %token PATH PIDFILE PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
65 %token TARGET TIMEOUT 
66
67 %union
68 {
69         char *str;
70 }
71
72 %token <str> STR
73
74 %%
75
76 statements:
77         |
78         statements statement
79         |
80         statements statement SEMICOLON
81         ;
82
83 statement:
84         debug
85         |
86         timeout
87         |
88         maxproc
89         |
90         pidfile
91         |
92         isns_server
93         |
94         isns_period
95         |
96         isns_timeout
97         |
98         auth_group
99         |
100         portal_group
101         |
102         target
103         ;
104
105 debug:          DEBUG STR
106         {
107                 uint64_t tmp;
108
109                 if (expand_number($2, &tmp) != 0) {
110                         yyerror("invalid numeric value");
111                         free($2);
112                         return (1);
113                 }
114                         
115                 conf->conf_debug = tmp;
116         }
117         ;
118
119 timeout:        TIMEOUT STR
120         {
121                 uint64_t tmp;
122
123                 if (expand_number($2, &tmp) != 0) {
124                         yyerror("invalid numeric value");
125                         free($2);
126                         return (1);
127                 }
128
129                 conf->conf_timeout = tmp;
130         }
131         ;
132
133 maxproc:        MAXPROC STR
134         {
135                 uint64_t tmp;
136
137                 if (expand_number($2, &tmp) != 0) {
138                         yyerror("invalid numeric value");
139                         free($2);
140                         return (1);
141                 }
142
143                 conf->conf_maxproc = tmp;
144         }
145         ;
146
147 pidfile:        PIDFILE STR
148         {
149                 if (conf->conf_pidfile_path != NULL) {
150                         log_warnx("pidfile specified more than once");
151                         free($2);
152                         return (1);
153                 }
154                 conf->conf_pidfile_path = $2;
155         }
156         ;
157
158 isns_server:    ISNS_SERVER STR
159         {
160                 int error;
161
162                 error = isns_new(conf, $2);
163                 free($2);
164                 if (error != 0)
165                         return (1);
166         }
167         ;
168
169 isns_period:    ISNS_PERIOD STR
170         {
171                 uint64_t tmp;
172
173                 if (expand_number($2, &tmp) != 0) {
174                         yyerror("invalid numeric value");
175                         free($2);
176                         return (1);
177                 }
178
179                 conf->conf_isns_period = tmp;
180         }
181         ;
182
183 isns_timeout:   ISNS_TIMEOUT STR
184         {
185                 uint64_t tmp;
186
187                 if (expand_number($2, &tmp) != 0) {
188                         yyerror("invalid numeric value");
189                         free($2);
190                         return (1);
191                 }
192
193                 conf->conf_isns_timeout = tmp;
194         }
195         ;
196
197 auth_group:     AUTH_GROUP auth_group_name
198     OPENING_BRACKET auth_group_entries CLOSING_BRACKET
199         {
200                 auth_group = NULL;
201         }
202         ;
203
204 auth_group_name:        STR
205         {
206                 /*
207                  * Make it possible to redefine default
208                  * auth-group. but only once.
209                  */
210                 if (strcmp($1, "default") == 0 &&
211                     conf->conf_default_ag_defined == false) {
212                         auth_group = auth_group_find(conf, $1);
213                         conf->conf_default_ag_defined = true;
214                 } else {
215                         auth_group = auth_group_new(conf, $1);
216                 }
217                 free($1);
218                 if (auth_group == NULL)
219                         return (1);
220         }
221         ;
222
223 auth_group_entries:
224         |
225         auth_group_entries auth_group_entry
226         |
227         auth_group_entries auth_group_entry SEMICOLON
228         ;
229
230 auth_group_entry:
231         auth_group_auth_type
232         |
233         auth_group_chap
234         |
235         auth_group_chap_mutual
236         |
237         auth_group_initiator_name
238         |
239         auth_group_initiator_portal
240         ;
241
242 auth_group_auth_type:   AUTH_TYPE STR
243         {
244                 int error;
245
246                 error = auth_group_set_type(auth_group, $2);
247                 free($2);
248                 if (error != 0)
249                         return (1);
250         }
251         ;
252
253 auth_group_chap:        CHAP STR STR
254         {
255                 const struct auth *ca;
256
257                 ca = auth_new_chap(auth_group, $2, $3);
258                 free($2);
259                 free($3);
260                 if (ca == NULL)
261                         return (1);
262         }
263         ;
264
265 auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR
266         {
267                 const struct auth *ca;
268
269                 ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
270                 free($2);
271                 free($3);
272                 free($4);
273                 free($5);
274                 if (ca == NULL)
275                         return (1);
276         }
277         ;
278
279 auth_group_initiator_name:      INITIATOR_NAME STR
280         {
281                 const struct auth_name *an;
282
283                 an = auth_name_new(auth_group, $2);
284                 free($2);
285                 if (an == NULL)
286                         return (1);
287         }
288         ;
289
290 auth_group_initiator_portal:    INITIATOR_PORTAL STR
291         {
292                 const struct auth_portal *ap;
293
294                 ap = auth_portal_new(auth_group, $2);
295                 free($2);
296                 if (ap == NULL)
297                         return (1);
298         }
299         ;
300
301 portal_group:   PORTAL_GROUP portal_group_name
302     OPENING_BRACKET portal_group_entries CLOSING_BRACKET
303         {
304                 portal_group = NULL;
305         }
306         ;
307
308 portal_group_name:      STR
309         {
310                 /*
311                  * Make it possible to redefine default
312                  * portal-group. but only once.
313                  */
314                 if (strcmp($1, "default") == 0 &&
315                     conf->conf_default_pg_defined == false) {
316                         portal_group = portal_group_find(conf, $1);
317                         conf->conf_default_pg_defined = true;
318                 } else {
319                         portal_group = portal_group_new(conf, $1);
320                 }
321                 free($1);
322                 if (portal_group == NULL)
323                         return (1);
324         }
325         ;
326
327 portal_group_entries:
328         |
329         portal_group_entries portal_group_entry
330         |
331         portal_group_entries portal_group_entry SEMICOLON
332         ;
333
334 portal_group_entry:
335         portal_group_discovery_auth_group
336         |
337         portal_group_discovery_filter
338         |
339         portal_group_listen
340         |
341         portal_group_listen_iser
342         |
343         portal_group_redirect
344         ;
345
346 portal_group_discovery_auth_group:      DISCOVERY_AUTH_GROUP STR
347         {
348                 if (portal_group->pg_discovery_auth_group != NULL) {
349                         log_warnx("discovery-auth-group for portal-group "
350                             "\"%s\" specified more than once",
351                             portal_group->pg_name);
352                         return (1);
353                 }
354                 portal_group->pg_discovery_auth_group =
355                     auth_group_find(conf, $2);
356                 if (portal_group->pg_discovery_auth_group == NULL) {
357                         log_warnx("unknown discovery-auth-group \"%s\" "
358                             "for portal-group \"%s\"",
359                             $2, portal_group->pg_name);
360                         return (1);
361                 }
362                 free($2);
363         }
364         ;
365
366 portal_group_discovery_filter:  DISCOVERY_FILTER STR
367         {
368                 int error;
369
370                 error = portal_group_set_filter(portal_group, $2);
371                 free($2);
372                 if (error != 0)
373                         return (1);
374         }
375         ;
376
377 portal_group_listen:    LISTEN STR
378         {
379                 int error;
380
381                 error = portal_group_add_listen(portal_group, $2, false);
382                 free($2);
383                 if (error != 0)
384                         return (1);
385         }
386         ;
387
388 portal_group_listen_iser:       LISTEN_ISER STR
389         {
390                 int error;
391
392                 error = portal_group_add_listen(portal_group, $2, true);
393                 free($2);
394                 if (error != 0)
395                         return (1);
396         }
397         ;
398
399 portal_group_redirect:  REDIRECT STR
400         {
401                 int error;
402
403                 error = portal_group_set_redirection(portal_group, $2);
404                 free($2);
405                 if (error != 0)
406                         return (1);
407         }
408         ;
409
410 target: TARGET target_name
411     OPENING_BRACKET target_entries CLOSING_BRACKET
412         {
413                 target = NULL;
414         }
415         ;
416
417 target_name:    STR
418         {
419                 target = target_new(conf, $1);
420                 free($1);
421                 if (target == NULL)
422                         return (1);
423         }
424         ;
425
426 target_entries:
427         |
428         target_entries target_entry
429         |
430         target_entries target_entry SEMICOLON
431         ;
432
433 target_entry:
434         target_alias
435         |
436         target_auth_group
437         |
438         target_auth_type
439         |
440         target_chap
441         |
442         target_chap_mutual
443         |
444         target_initiator_name
445         |
446         target_initiator_portal
447         |
448         target_portal_group
449         |
450         target_redirect
451         |
452         target_lun
453         ;
454
455 target_alias:   ALIAS STR
456         {
457                 if (target->t_alias != NULL) {
458                         log_warnx("alias for target \"%s\" "
459                             "specified more than once", target->t_name);
460                         return (1);
461                 }
462                 target->t_alias = $2;
463         }
464         ;
465
466 target_auth_group:      AUTH_GROUP STR
467         {
468                 if (target->t_auth_group != NULL) {
469                         if (target->t_auth_group->ag_name != NULL)
470                                 log_warnx("auth-group for target \"%s\" "
471                                     "specified more than once", target->t_name);
472                         else
473                                 log_warnx("cannot use both auth-group and explicit "
474                                     "authorisations for target \"%s\"",
475                                     target->t_name);
476                         return (1);
477                 }
478                 target->t_auth_group = auth_group_find(conf, $2);
479                 if (target->t_auth_group == NULL) {
480                         log_warnx("unknown auth-group \"%s\" for target "
481                             "\"%s\"", $2, target->t_name);
482                         return (1);
483                 }
484                 free($2);
485         }
486         ;
487
488 target_auth_type:       AUTH_TYPE STR
489         {
490                 int error;
491
492                 if (target->t_auth_group != NULL) {
493                         if (target->t_auth_group->ag_name != NULL) {
494                                 log_warnx("cannot use both auth-group and "
495                                     "auth-type for target \"%s\"",
496                                     target->t_name);
497                                 return (1);
498                         }
499                 } else {
500                         target->t_auth_group = auth_group_new(conf, NULL);
501                         if (target->t_auth_group == NULL) {
502                                 free($2);
503                                 return (1);
504                         }
505                         target->t_auth_group->ag_target = target;
506                 }
507                 error = auth_group_set_type(target->t_auth_group, $2);
508                 free($2);
509                 if (error != 0)
510                         return (1);
511         }
512         ;
513
514 target_chap:    CHAP STR STR
515         {
516                 const struct auth *ca;
517
518                 if (target->t_auth_group != NULL) {
519                         if (target->t_auth_group->ag_name != NULL) {
520                                 log_warnx("cannot use both auth-group and "
521                                     "chap for target \"%s\"",
522                                     target->t_name);
523                                 free($2);
524                                 free($3);
525                                 return (1);
526                         }
527                 } else {
528                         target->t_auth_group = auth_group_new(conf, NULL);
529                         if (target->t_auth_group == NULL) {
530                                 free($2);
531                                 free($3);
532                                 return (1);
533                         }
534                         target->t_auth_group->ag_target = target;
535                 }
536                 ca = auth_new_chap(target->t_auth_group, $2, $3);
537                 free($2);
538                 free($3);
539                 if (ca == NULL)
540                         return (1);
541         }
542         ;
543
544 target_chap_mutual:     CHAP_MUTUAL STR STR STR STR
545         {
546                 const struct auth *ca;
547
548                 if (target->t_auth_group != NULL) {
549                         if (target->t_auth_group->ag_name != NULL) {
550                                 log_warnx("cannot use both auth-group and "
551                                     "chap-mutual for target \"%s\"",
552                                     target->t_name);
553                                 free($2);
554                                 free($3);
555                                 free($4);
556                                 free($5);
557                                 return (1);
558                         }
559                 } else {
560                         target->t_auth_group = auth_group_new(conf, NULL);
561                         if (target->t_auth_group == NULL) {
562                                 free($2);
563                                 free($3);
564                                 free($4);
565                                 free($5);
566                                 return (1);
567                         }
568                         target->t_auth_group->ag_target = target;
569                 }
570                 ca = auth_new_chap_mutual(target->t_auth_group,
571                     $2, $3, $4, $5);
572                 free($2);
573                 free($3);
574                 free($4);
575                 free($5);
576                 if (ca == NULL)
577                         return (1);
578         }
579         ;
580
581 target_initiator_name:  INITIATOR_NAME STR
582         {
583                 const struct auth_name *an;
584
585                 if (target->t_auth_group != NULL) {
586                         if (target->t_auth_group->ag_name != NULL) {
587                                 log_warnx("cannot use both auth-group and "
588                                     "initiator-name for target \"%s\"",
589                                     target->t_name);
590                                 free($2);
591                                 return (1);
592                         }
593                 } else {
594                         target->t_auth_group = auth_group_new(conf, NULL);
595                         if (target->t_auth_group == NULL) {
596                                 free($2);
597                                 return (1);
598                         }
599                         target->t_auth_group->ag_target = target;
600                 }
601                 an = auth_name_new(target->t_auth_group, $2);
602                 free($2);
603                 if (an == NULL)
604                         return (1);
605         }
606         ;
607
608 target_initiator_portal:        INITIATOR_PORTAL STR
609         {
610                 const struct auth_portal *ap;
611
612                 if (target->t_auth_group != NULL) {
613                         if (target->t_auth_group->ag_name != NULL) {
614                                 log_warnx("cannot use both auth-group and "
615                                     "initiator-portal for target \"%s\"",
616                                     target->t_name);
617                                 free($2);
618                                 return (1);
619                         }
620                 } else {
621                         target->t_auth_group = auth_group_new(conf, NULL);
622                         if (target->t_auth_group == NULL) {
623                                 free($2);
624                                 return (1);
625                         }
626                         target->t_auth_group->ag_target = target;
627                 }
628                 ap = auth_portal_new(target->t_auth_group, $2);
629                 free($2);
630                 if (ap == NULL)
631                         return (1);
632         }
633         ;
634
635 target_portal_group:    PORTAL_GROUP STR
636         {
637                 if (target->t_portal_group != NULL) {
638                         log_warnx("portal-group for target \"%s\" "
639                             "specified more than once", target->t_name);
640                         free($2);
641                         return (1);
642                 }
643                 target->t_portal_group = portal_group_find(conf, $2);
644                 if (target->t_portal_group == NULL) {
645                         log_warnx("unknown portal-group \"%s\" for target "
646                             "\"%s\"", $2, target->t_name);
647                         free($2);
648                         return (1);
649                 }
650                 free($2);
651         }
652         ;
653
654 target_redirect:        REDIRECT STR
655         {
656                 int error;
657
658                 error = target_set_redirection(target, $2);
659                 free($2);
660                 if (error != 0)
661                         return (1);
662         }
663         ;
664
665 target_lun:     LUN lun_number
666     OPENING_BRACKET lun_entries CLOSING_BRACKET
667         {
668                 lun = NULL;
669         }
670         ;
671
672 lun_number:     STR
673         {
674                 uint64_t tmp;
675
676                 if (expand_number($1, &tmp) != 0) {
677                         yyerror("invalid numeric value");
678                         free($1);
679                         return (1);
680                 }
681
682                 lun = lun_new(target, tmp);
683                 if (lun == NULL)
684                         return (1);
685         }
686         ;
687
688 lun_entries:
689         |
690         lun_entries lun_entry
691         |
692         lun_entries lun_entry SEMICOLON
693         ;
694
695 lun_entry:
696         lun_backend
697         |
698         lun_blocksize
699         |
700         lun_device_id
701         |
702         lun_option
703         |
704         lun_path
705         |
706         lun_serial
707         |
708         lun_size
709         ;
710
711 lun_backend:    BACKEND STR
712         {
713                 if (lun->l_backend != NULL) {
714                         log_warnx("backend for lun %d, target \"%s\" "
715                             "specified more than once",
716                             lun->l_lun, target->t_name);
717                         free($2);
718                         return (1);
719                 }
720                 lun_set_backend(lun, $2);
721                 free($2);
722         }
723         ;
724
725 lun_blocksize:  BLOCKSIZE STR
726         {
727                 uint64_t tmp;
728
729                 if (expand_number($2, &tmp) != 0) {
730                         yyerror("invalid numeric value");
731                         free($2);
732                         return (1);
733                 }
734
735                 if (lun->l_blocksize != 0) {
736                         log_warnx("blocksize for lun %d, target \"%s\" "
737                             "specified more than once",
738                             lun->l_lun, target->t_name);
739                         return (1);
740                 }
741                 lun_set_blocksize(lun, tmp);
742         }
743         ;
744
745 lun_device_id:  DEVICE_ID STR
746         {
747                 if (lun->l_device_id != NULL) {
748                         log_warnx("device_id for lun %d, target \"%s\" "
749                             "specified more than once",
750                             lun->l_lun, target->t_name);
751                         free($2);
752                         return (1);
753                 }
754                 lun_set_device_id(lun, $2);
755                 free($2);
756         }
757         ;
758
759 lun_option:     OPTION STR STR
760         {
761                 struct lun_option *clo;
762
763                 clo = lun_option_new(lun, $2, $3);
764                 free($2);
765                 free($3);
766                 if (clo == NULL)
767                         return (1);
768         }
769         ;
770
771 lun_path:       PATH STR
772         {
773                 if (lun->l_path != NULL) {
774                         log_warnx("path for lun %d, target \"%s\" "
775                             "specified more than once",
776                             lun->l_lun, target->t_name);
777                         free($2);
778                         return (1);
779                 }
780                 lun_set_path(lun, $2);
781                 free($2);
782         }
783         ;
784
785 lun_serial:     SERIAL STR
786         {
787                 if (lun->l_serial != NULL) {
788                         log_warnx("serial for lun %d, target \"%s\" "
789                             "specified more than once",
790                             lun->l_lun, target->t_name);
791                         free($2);
792                         return (1);
793                 }
794                 lun_set_serial(lun, $2);
795                 free($2);
796         }
797         ;
798
799 lun_size:       SIZE STR
800         {
801                 uint64_t tmp;
802
803                 if (expand_number($2, &tmp) != 0) {
804                         yyerror("invalid numeric value");
805                         free($2);
806                         return (1);
807                 }
808
809                 if (lun->l_size != 0) {
810                         log_warnx("size for lun %d, target \"%s\" "
811                             "specified more than once",
812                             lun->l_lun, target->t_name);
813                         return (1);
814                 }
815                 lun_set_size(lun, tmp);
816         }
817         ;
818 %%
819
820 void
821 yyerror(const char *str)
822 {
823
824         log_warnx("error in configuration file at line %d near '%s': %s",
825             lineno, yytext, str);
826 }
827
828 static void
829 check_perms(const char *path)
830 {
831         struct stat sb;
832         int error;
833
834         error = stat(path, &sb);
835         if (error != 0) {
836                 log_warn("stat");
837                 return;
838         }
839         if (sb.st_mode & S_IWOTH) {
840                 log_warnx("%s is world-writable", path);
841         } else if (sb.st_mode & S_IROTH) {
842                 log_warnx("%s is world-readable", path);
843         } else if (sb.st_mode & S_IXOTH) {
844                 /*
845                  * Ok, this one doesn't matter, but still do it,
846                  * just for consistency.
847                  */
848                 log_warnx("%s is world-executable", path);
849         }
850
851         /*
852          * XXX: Should we also check for owner != 0?
853          */
854 }
855
856 struct conf *
857 conf_new_from_file(const char *path)
858 {
859         struct auth_group *ag;
860         struct portal_group *pg;
861         int error;
862
863         log_debugx("obtaining configuration from %s", path);
864
865         conf = conf_new();
866
867         ag = auth_group_new(conf, "default");
868         assert(ag != NULL);
869
870         ag = auth_group_new(conf, "no-authentication");
871         assert(ag != NULL);
872         ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
873
874         ag = auth_group_new(conf, "no-access");
875         assert(ag != NULL);
876         ag->ag_type = AG_TYPE_DENY;
877
878         pg = portal_group_new(conf, "default");
879         assert(pg != NULL);
880
881         yyin = fopen(path, "r");
882         if (yyin == NULL) {
883                 log_warn("unable to open configuration file %s", path);
884                 conf_delete(conf);
885                 return (NULL);
886         }
887         check_perms(path);
888         lineno = 1;
889         yyrestart(yyin);
890         error = yyparse();
891         auth_group = NULL;
892         portal_group = NULL;
893         target = NULL;
894         lun = NULL;
895         fclose(yyin);
896         if (error != 0) {
897                 conf_delete(conf);
898                 return (NULL);
899         }
900
901         if (conf->conf_default_ag_defined == false) {
902                 log_debugx("auth-group \"default\" not defined; "
903                     "going with defaults");
904                 ag = auth_group_find(conf, "default");
905                 assert(ag != NULL);
906                 ag->ag_type = AG_TYPE_DENY;
907         }
908
909         if (conf->conf_default_pg_defined == false) {
910                 log_debugx("portal-group \"default\" not defined; "
911                     "going with defaults");
912                 pg = portal_group_find(conf, "default");
913                 assert(pg != NULL);
914                 portal_group_add_listen(pg, "0.0.0.0:3260", false);
915                 portal_group_add_listen(pg, "[::]:3260", false);
916         }
917
918         conf->conf_kernel_port_on = true;
919
920         error = conf_verify(conf);
921         if (error != 0) {
922                 conf_delete(conf);
923                 return (NULL);
924         }
925
926         return (conf);
927 }