From a68224153b9873a32487be547461ed7b57111d5f Mon Sep 17 00:00:00 2001 From: Tim Waugh Date: Jul 01 2008 16:09:38 +0000 Subject: Handle service/protocol format for configuration file. * src/portreserve.c (reserve): Change return type to struct map pointer, and bind for each protocol specified. (portreserve): Handle '*' in the same way as a particular service, as a service may have more than one mapping. * doc/portreserve.xml: Updated. --- diff --git a/ChangeLog b/ChangeLog index 39547ad..003ec59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2008-07-01 Tim Waugh + + * src/portreserve.c (reserve): Change return type to struct map + pointer, and bind for each protocol specified. + (portreserve): Handle '*' in the same way as a particular service, + as a service may have more than one mapping. + + * doc/portreserve.xml: Updated. + 2008-06-30 Tim Waugh * configure.in: Version 0.0.2. diff --git a/doc/portreserve.xml b/doc/portreserve.xml index 818dcfa..6d84918 100644 --- a/doc/portreserve.xml +++ b/doc/portreserve.xml @@ -7,7 +7,7 @@ portreserve - 3 September 2003 + 1 July 2008 Tim Waugh @@ -24,8 +24,8 @@ portreserve - reserve TCP ports to prevent portmap mapping - them + reserve ports to prevent portmap mapping + them @@ -109,7 +109,7 @@ portreserve - 3 September 2003 + 1 July 2008 Tim Waugh @@ -126,7 +126,7 @@ portrelease - release previously-reserved TCP ports + release previously-reserved ports diff --git a/src/portreserve.c b/src/portreserve.c index e64d971..1f635ea 100644 --- a/src/portreserve.c +++ b/src/portreserve.c @@ -110,48 +110,96 @@ real_file (const char *name) return 1; } -static int -reserve (const char *file) +static void +no_memory (void) +{ + exit (1); +} + +static struct map * +reserve (const char *file, const char *client) { - struct sockaddr_in sin; - struct servent *serv; + struct map *maps = NULL; char service[100]; + char *protocols[2] = { "tcp", "udp" }; + size_t num_protocols = 2; + size_t i; char *p; - int sd; FILE *f = fopen (file, "r"); if (!f) - return -1; + return NULL; p = fgets (service, sizeof (service), f); fclose (f); if (!p) - return -1; - p = strchr (service, '\n'); - if (p) + return NULL; + p += strcspn (service, "/\n"); + if (*p == '/') { *p = '\0'; - serv = getservbyname (service, NULL); - if (!serv) { - char *endptr; - int port = strtol (service, &endptr, 10); - if (service == endptr) - return -1; - serv = getservbyport (htons (port), NULL); - if (!serv) - return -1; + protocols[0] = p + 1; + p = strchr (protocols[0], '\n'); + num_protocols = 1; } - sd = socket (PF_INET, SOCK_STREAM, 0); - if (sd == -1) - return -1; - sin.sin_port = (in_port_t) serv->s_port; - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - if (bind (sd, (struct sockaddr *) &sin, sizeof (sin)) == -1) { - error (0, errno, "bind"); - return -1; + if (p) + *p = '\0'; + + for (i = 0; i < num_protocols; i++) { + struct map *map; + struct sockaddr_in sin; + int sd; + int type; + const char *protocol = protocols[i]; + struct servent *serv = getservbyname (service, protocol); + if (serv) + sin.sin_port = (in_port_t) serv->s_port; + else { + char *endptr; + int port = strtol (service, &endptr, 10); + if (service == endptr) + /* Not found for this protocol. */ + continue; + + /* Numeric entry */ + sin.sin_port = htons (port); + } + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + + if (!strcmp (protocol, "udp")) + type = SOCK_DGRAM; + else + type = SOCK_STREAM; + + sd = socket (PF_INET, type, 0); + if (sd == -1) { + if (debug) + fprintf (stderr, "Unable to create %s socket\n", + protocol); + continue; + } + + if (bind (sd, (struct sockaddr *) &sin, sizeof (sin)) == -1) { + error (0, errno, "bind"); + continue; + } + + + map = malloc (sizeof (*map)); + if (!map) + no_memory (); + map->socket = sd; + map->next = maps; + map->service = strdup (client); + if (!map->service) + no_memory (); + maps = map; + + if (debug) + fprintf (stderr, "Reserved %d/%s for %s\n", + ntohs (sin.sin_port), protocol, client); } - if (debug) - fprintf (stderr, "Reserved port %d for %s\n", - ntohs (sin.sin_port), strrchr (file, '/') + 1); - return sd; + + return maps; } static int @@ -179,12 +227,6 @@ unix_socket (void) return s; } -static void -no_memory (void) -{ - exit (1); -} - static int portreserve (void) { @@ -202,22 +244,21 @@ portreserve (void) if (!cfgdir) return -1; while ((d = readdir (cfgdir)) != NULL) { - struct map *map; + struct map *newmaps, *p; int s; if (!real_file (d->d_name)) continue; strcpy (cfgf, d->d_name); - if ((s = reserve (cfgfile)) == -1) + if ((newmaps = reserve (cfgfile, d->d_name)) == NULL) continue; - map = malloc (sizeof (*map)); - if (!map) - no_memory (); - map->socket = s; - map->next = maps; - map->service = strdup (d->d_name); - if (!map->service) - no_memory (); - maps = map; + + for (p = newmaps; p && p->next != NULL; p = newmaps->next) + ; + if (p) + p->next = maps; + + if (newmaps) + maps = newmaps; } closedir (cfgdir); @@ -237,7 +278,8 @@ portreserve (void) prev = &maps; m = maps; while (m) { - if (!strcmp (service, "*")) { + if (!strcmp (service, "*") || + !strcmp (m->service, service)) { struct map *next = m->next; if (debug) @@ -249,16 +291,6 @@ portreserve (void) free (m); m = next; maps = NULL; - } else if (!strcmp (m->service, service)) { - if (debug) - fprintf (stderr, - "Released service " - "%s\n", m->service); - close (m->socket); - *prev = m->next; - free (m->service); - free (m); - break; } else { prev = &m->next; m = *prev;