From 0983872cf4a7e078f73084e340bca0315e8e92bf Mon Sep 17 00:00:00 2001 From: Louie Date: Apr 30 2018 00:35:27 +0000 Subject: [PATCH 1/2] Allow tcp6 and udp6 ports to be reserved --- diff --git a/src/portreserve.c b/src/portreserve.c index 672f967..6e1715b 100644 --- a/src/portreserve.c +++ b/src/portreserve.c @@ -81,6 +81,7 @@ struct map { char *service; int type; + int family; in_port_t port; int socket; @@ -131,8 +132,8 @@ reserve (const char *file, const char *client) for (;;) { char service[100]; - char *protocols[2] = { "tcp", "udp" }; - size_t num_protocols = 2; + char *protocols[4] = { "tcp", "udp", "tcp6", "udp6" }; + size_t num_protocols = 4; size_t i; char *p = fgets (service, sizeof (service), f); @@ -154,14 +155,24 @@ reserve (const char *file, const char *client) for (i = 0; i < num_protocols; i++) { struct map *map; - struct sockaddr_in sin; + struct sockaddr_in sin4; + struct sockaddr_in6 sin6; + struct sockaddr* sin; + int sin_size; int sd; int type; const char *protocol = protocols[i]; struct servent *serv = getservbyname (service, protocol); + int net_port; + int family; + int proto_len = strlen(protocol); + + memset(&sin4, 0, sizeof(sin4)); + memset(&sin6, 0, sizeof(sin6)); + if (serv) - sin.sin_port = (in_port_t) serv->s_port; + net_port = (in_port_t) serv->s_port; else { char *endptr; int port = strtol (service, &endptr, 10); @@ -170,30 +181,64 @@ reserve (const char *file, const char *client) continue; /* Numeric entry */ - sin.sin_port = htons (port); + net_port = htons (port); } - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - - if (!strcmp (protocol, "udp")) + if (!strncmp (protocol, "udp", proto_len)) { type = SOCK_DGRAM; - else + family = AF_INET; + sin4.sin_family = AF_INET; + sin4.sin_addr.s_addr = INADDR_ANY; + sin4.sin_port = net_port; + } + else if (!strncmp (protocol, "tcp", proto_len)) { type = SOCK_STREAM; + family = AF_INET; + sin4.sin_family = AF_INET; + sin4.sin_addr.s_addr = INADDR_ANY; + sin4.sin_port = net_port; + } + else if (!strncmp (protocol, "udp6", proto_len)) { + type = SOCK_DGRAM; + family = AF_INET6; + sin6.sin6_family = AF_INET6; + sin6.sin6_addr = in6addr_any; + sin6.sin6_port = net_port; + } + else if (!strncmp (protocol, "tcp6", proto_len)) { + type = SOCK_STREAM; + family = AF_INET6; + sin6.sin6_family = AF_INET6; + sin6.sin6_addr = in6addr_any; + sin6.sin6_port = net_port; + } + + if ( family == AF_INET ) { + sin = (struct sockaddr*)&sin4; + sin_size = sizeof(sin4); + } else { + sin = (struct sockaddr*)&sin6; + sin_size = sizeof(sin6); + } - sd = socket (PF_INET, type, 0); + sd = socket (family, type, 0); if (sd == -1) { if (debug) - fprintf (stderr, - "Unable to create %s socket\n", - protocol); + fprintf (stderr, + "Unable to create %s socket\n", + protocol); continue; } - if (bind (sd, (struct sockaddr *) &sin, - sizeof (sin)) == -1) { + if ( family == AF_INET6 ) { + int on = 1; + setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)); + } + + if (bind (sd, sin, + sin_size) != 0) { error (0, errno, "bind for %s (%d/%s)", - client, ntohs (sin.sin_port), + client, ntohs (net_port), protocol); if (errno != EADDRINUSE) continue; @@ -202,14 +247,15 @@ reserve (const char *file, const char *client) * it will cause the conflicting service to * also be released */ - sd = -1; + sd = -1; } map = malloc (sizeof (*map)); if (!map) no_memory (); map->type = type; - map->port = sin.sin_port; + map->family = family; + map->port = net_port; map->socket = sd; map->next = maps; map->service = strdup (client); @@ -219,8 +265,8 @@ reserve (const char *file, const char *client) if (sd != -1 && debug) fprintf (stderr, "Reserved %d/%s for %s\n", - ntohs (sin.sin_port), - protocol, client); + ntohs (net_port), + protocol, client); } } @@ -263,7 +309,8 @@ release_socket(struct map **prev, struct map *map) if (debug) fprintf (stderr, "Released service %s (%d/%s)\n", map->service, ntohs (map->port), - map->type == SOCK_STREAM ? "tcp" : "udp"); + map->type == SOCK_STREAM ? ( map->family == AF_INET ? "tcp" : "tcp6" ) + : ( map->family == AF_INET ? "udp" : "udp6" )); } free (map->service); @@ -274,7 +321,7 @@ release_socket(struct map **prev, struct map *map) } static void -release_by_port(struct map **mapsptr, int type, in_port_t port) +release_by_port(struct map **mapsptr, int type, int family, in_port_t port) { struct map *m, **prev; int output = 0; @@ -282,7 +329,7 @@ release_by_port(struct map **mapsptr, int type, in_port_t port) prev = mapsptr; m = *mapsptr; while (m) { - if (m->type == type && m->port == port) { + if (m->type == type && m->family == family && m->port == port) { if (!output) { output = 1; fprintf (stderr, @@ -355,7 +402,7 @@ portreserve (void) in_port_t port = m->port; release_socket(prev, m); - release_by_port(&maps, type, port); + release_by_port(&maps, type, m->family, port); /* Start at the beginning of the list again */ prev = &maps; From 982053df021ea513664306eef35581d48f4f158d Mon Sep 17 00:00:00 2001 From: Louie Date: Apr 30 2018 16:04:49 +0000 Subject: [PATCH 2/2] Tidy up protocol identification --- diff --git a/src/portreserve.c b/src/portreserve.c index 6e1715b..c3b671f 100644 --- a/src/portreserve.c +++ b/src/portreserve.c @@ -166,7 +166,6 @@ reserve (const char *file, const char *client) protocol); int net_port; int family; - int proto_len = strlen(protocol); memset(&sin4, 0, sizeof(sin4)); memset(&sin6, 0, sizeof(sin6)); @@ -184,28 +183,28 @@ reserve (const char *file, const char *client) net_port = htons (port); } - if (!strncmp (protocol, "udp", proto_len)) { + if (!strcmp (protocol, "udp")) { type = SOCK_DGRAM; family = AF_INET; sin4.sin_family = AF_INET; sin4.sin_addr.s_addr = INADDR_ANY; sin4.sin_port = net_port; } - else if (!strncmp (protocol, "tcp", proto_len)) { + else if (!strcmp (protocol, "tcp")) { type = SOCK_STREAM; family = AF_INET; sin4.sin_family = AF_INET; sin4.sin_addr.s_addr = INADDR_ANY; sin4.sin_port = net_port; } - else if (!strncmp (protocol, "udp6", proto_len)) { + else if (!strcmp (protocol, "udp6")) { type = SOCK_DGRAM; family = AF_INET6; sin6.sin6_family = AF_INET6; sin6.sin6_addr = in6addr_any; sin6.sin6_port = net_port; } - else if (!strncmp (protocol, "tcp6", proto_len)) { + else if (!strcmp (protocol, "tcp6")) { type = SOCK_STREAM; family = AF_INET6; sin6.sin6_family = AF_INET6;