2 * (c) Copyright 1998-2001 by Rob Braun
3 * All rights reserved. The file named COPYRIGHT specifies the terms
4 * and conditions for redistribution.
28 static int get_next_inet_entry( int fd, pset_h sconfs,
29 struct service_config *defaults);
31 void parse_inet_conf_file( int fd, struct configuration *confp )
33 pset_h sconfs = CNF_SERVICE_CONFS( confp );
34 struct service_config *default_config = CNF_DEFAULTS( confp );
37 iter = psi_create (sconfs);
41 if (get_next_inet_entry(fd, sconfs, default_config) == -2)
48 static int get_next_inet_entry( int fd, pset_h sconfs,
49 struct service_config *defaults)
53 char *line = next_line(fd);
54 struct service_config *scp, *tmp;
56 const char *func = "get_next_inet_entry";
57 char *name = NULL, *rpcvers = NULL, *rpcproto = NULL;
58 char *group, *proto, *stype;
59 const struct name_value *nvp;
60 struct protoent *pep ;
63 const char *dot = ".";
64 const char *slash = "/";
67 if( line == CHAR_NULL )
70 strp = str_parse( line, " \t", STR_RETURN_ERROR, INT_NULL ) ;
73 parsemsg( LOG_CRIT, func, "inetd.conf - str_parse failed" ) ;
77 if( (args = pset_create(10,10)) == NULL )
83 /* Break the line into components, based on spaces */
84 while( (p = str_component( strp )) )
86 if( pset_add(args, p) == NULL )
88 parsemsg( LOG_CRIT, func, ES_NOMEM );
95 /* get the service name */
96 name = new_string((char *)pset_pointer( args, 0 ));
98 parsemsg( LOG_ERR, func, "inetd.conf - Invalid service name" );
103 /* Check to find the '/' for specifying RPC version numbers */
104 if( (rpcvers = strstr(name, slash)) != NULL ) {
109 scp = sc_alloc( name );
117 * sc_alloc makes its own copy of name. At this point, sc_alloc worked
118 * so we will free our copy to avoid leaks.
122 /* Replicate inetd behavior in this regard. Also makes sure the
123 * service actually works on system where setgroups(0,NULL) doesn't
126 SC_GROUPS(scp) = YES;
127 SC_SPECIFY( scp, A_GROUPS );
129 /* Get the socket type (stream dgram) */
130 stype = (char *)pset_pointer(args, 1);
131 if( stype == NULL ) {
132 parsemsg( LOG_ERR, func, "inetd.conf - Invalid socket type" );
137 nvp = nv_find_value( socket_types, stype );
140 parsemsg( LOG_ERR, func, "inetd.conf - Bad socket type: %s", p);
146 SC_SOCKET_TYPE(scp) = nvp->value;
148 /* Get the protocol type */
149 proto = (char *)pset_pointer(args,2);
150 if( strstr(proto, "rpc") != NULL )
153 struct rpc_data *rdp = SC_RPCDATA( scp ) ;
155 if( rpcvers == NULL ) {
162 p = strchr(rpcvers, '-');
163 if( p && parse_int(rpcvers, 10, '-', &rpcmin) == 0 ) {
164 if( parse_base10(p + 1, &rpcmax) || rpcmin > rpcmax ) {
170 if( parse_base10(rpcvers, &rpcmin) ) {
179 /* now have min and max rpc versions */
180 rdp->rd_min_version = rpcmin;
181 rdp->rd_max_version = rpcmax;
183 rpcproto = strstr(proto, slash);
184 if( rpcproto == NULL ) {
185 parsemsg( LOG_ERR, func, "inetd.conf - bad rpc version numbers" );
194 /* Set the RPC type field */
195 nvp = nv_find_value( service_types, "RPC" );
198 parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
204 M_SET(SC_TYPE(scp), nvp->value);
206 if ( ( pep = getprotobyname( proto ) ) == NULL )
208 parsemsg( LOG_ERR, func, "inetd.conf - Protocol %s not in /etc/protocols",
215 SC_PROTONAME(scp) = new_string( proto ) ;
216 if ( SC_PROTONAME(scp) == NULL )
218 out_of_memory( func ) ;
223 SC_PROTOVAL(scp) = pep->p_proto;
224 SC_SPECIFY(scp, A_PROTOCOL);
226 /* Get the wait attribute */
227 p = (char *)pset_pointer(args, 3);
229 parsemsg( LOG_ERR, func, "inetd.conf - No value specified for wait" );
233 if ( EQ( p, "wait" ) )
235 else if ( EQ( p, "nowait" ) )
238 parsemsg( LOG_ERR, func, "inetd.conf - Bad value for wait: %s", p ) ;
240 /* Get the user to run as */
241 p = (char *)pset_pointer(args, 4);
243 parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" );
247 if( (group = strstr(p, dot)) )
252 grp = (struct group *)getgrnam( (char *)group ) ;
255 parsemsg( LOG_ERR, func, "inetd.conf - Unknown group: %s", group ) ;
261 SC_GID(scp) = ((struct group *)grp)->gr_gid;
262 SC_SPECIFY( scp, A_GROUP );
268 parsemsg( LOG_ERR, func, "inetd.conf - Unknown user: %s", p ) ;
273 str_fill( pw->pw_passwd, ' ' );
274 SC_UID(scp) = pw->pw_uid;
275 SC_USER_GID(scp) = pw->pw_gid;
277 /* Get server name, or flag as internal */
278 p = (char *)pset_pointer(args, 5);
280 parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" );
284 if( EQ( p, "internal" ) )
286 nvp = nv_find_value( service_types, "INTERNAL" );
289 parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
295 M_SET(SC_TYPE(scp), nvp->value);
297 if( EQ( SC_NAME(scp), "time" ) ) {
298 if( EQ( proto, "stream" ) )
299 SC_ID(scp) = new_string("time-stream");
301 SC_ID(scp) = new_string("time-dgram");
304 if( EQ( SC_NAME(scp), "daytime" ) ) {
305 if( EQ( proto, "stream" ) )
306 SC_ID(scp) = new_string("daytime-stream");
308 SC_ID(scp) = new_string("daytime-dgram");
311 if( EQ( SC_NAME(scp), "chargen" ) ) {
312 if( EQ( proto, "stream" ) )
313 SC_ID(scp) = new_string("chargen-stream");
315 SC_ID(scp) = new_string("chargen-dgram");
318 if( EQ( SC_NAME(scp), "echo" ) ) {
319 if( EQ( proto, "stream" ) )
320 SC_ID(scp) = new_string("echo-stream");
322 SC_ID(scp) = new_string("echo-dgram");
325 if( EQ( SC_NAME(scp), "discard" ) )
327 parsemsg(LOG_WARNING, func,
328 "inetd.conf - service discard not supported");
336 SC_SERVER(scp) = new_string( p );
337 if ( SC_SERVER(scp) == NULL )
339 out_of_memory( func ) ;
344 SC_SPECIFY( scp, A_SERVER);
347 SC_SERVER_ARGV(scp) = (char **)argv_alloc(pset_count(args)+1);
349 for( u = 0; u < pset_count(args)-6 ; u++ )
351 p = new_string((char *)pset_pointer(args, u+6));
354 for ( i = 1 ; i < u ; i++ )
355 free( SC_SERVER_ARGV(scp)[i] );
356 free( SC_SERVER_ARGV(scp) );
361 SC_SERVER_ARGV(scp)[u] = p;
363 /* Set the reuse flag, as this is the default for inetd */
364 nvp = nv_find_value( service_flags, "REUSE" );
367 parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
372 M_SET(SC_XFLAGS(scp), nvp->value);
374 /* Set the NOLIBWRAP flag, since inetd doesn't have libwrap built in */
375 nvp = nv_find_value( service_flags, "NOLIBWRAP" );
378 parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
383 M_SET(SC_XFLAGS(scp), nvp->value);
385 /* Set the NAMEINARGS flag, as that's the default for inetd */
386 nvp = nv_find_value( service_flags, "NAMEINARGS" );
389 parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
394 M_SET(SC_XFLAGS(scp), nvp->value);
395 SC_SPECIFY( scp, A_SERVER_ARGS );
397 if ( (SC_ID(scp) = new_string( SC_NAME(scp) )) )
398 SC_PRESENT( scp, A_ID ) ;
401 out_of_memory( func ) ;
408 SC_SPECIFY( scp, A_PROTOCOL );
409 SC_SPECIFY( scp, A_USER );
410 SC_SPECIFY( scp, A_SOCKET_TYPE );
411 SC_SPECIFY( scp, A_WAIT );
413 for ( tmp = SCP( psi_start( iter ) ) ; tmp ; tmp = SCP( psi_next(iter)) ){
414 if (EQ(SC_ID(scp), SC_ID(tmp))) {
415 parsemsg(LOG_DEBUG, func, "removing duplicate service %s", SC_NAME(scp));
422 if( scp && ! pset_add(sconfs, scp) )
424 out_of_memory( func );
432 parsemsg( LOG_DEBUG, func, "added service %s", SC_NAME(scp));