tderr, "ipfirewall: port number out of range (%d)\n", port); exit (1); } return (port); } else { struct servent *sptr; sptr = getservbyname (arg, proto_name); if (sptr == NULL) { fprintf (stderr, "ipfirewall: unknown %s service \"%s\"\n", proto_name, arg); exit (1); } return (ntohs (sptr->s_port)); } } int get_ports (char ***argv_ptr, u_short * ports, int min_ports, int max_ports, void (*usage) (ipf_kind), ipf_kind kind, const char *proto_name) { int ix; char *arg; int sign; ix = 0; sign = 1; while ((arg = **argv_ptr) != NULL && strcmp (arg, "from") != 0 && strcmp (arg, "to") != 0) { char *p; /* * Check that we havn't found too many port numbers. * We do this here instead of with another condition on the while loop * so that the caller can assume that the next parameter is NOT a port number. */ if (ix >= max_ports) { fprintf (stderr, "ipfirewall: too many port numbers (max %d, got at least %d, next parm=\"%s\")\n", max_ports, max_ports + 1, arg); exit (1); } if ((p = strchr (arg, ':')) == NULL) { ports[ix++] = get_one_port (arg, usage, kind, proto_name); } else { if (ix > 0) { fprintf (stderr, "ipfirewall: port ranges are only allowed for the first port value pair (%s)\n", arg); exit (1); } if (max_ports > 1) { char *tbuf; tbuf = malloc ((p - arg) + 1); strncpy (tbuf, arg, p - arg); tbuf[p - arg] = '\0'; ports[ix++] = get_one_port (tbuf, usage, kind, proto_name); ports[ix++] = get_one_port (p + 1, usage, kind, proto_name); sign = -1; } else { fprintf (stderr, "ipfirewall: port range not allowed here (%s)\n", arg); exit (1); } } *argv_ptr += 1; } if (ix < min_ports) { if (min_ports == 1) { fprintf (stderr, "ipfirewall: missing port number%s\n", max_ports == 1 ? "" : "(s)"); } else { fprintf (stderr, "ipfirewall: not enough port numbers (expected %d, got %d)\n", min_ports, ix); } exit (1); } return (sign * ix); } void check_usage (ipf_kind kind) { fprintf (stderr, "usage: ipfirewall check%s ...\n", ipf_names[kind]); } void check (ipf_kind kind, int socket_fd, char **argv) { int protocol; struct iphdr *packet; char *proto_name; packet = (struct iphdr *) malloc (sizeof (struct iphdr) + sizeof (struct tcphdr)); packet->version = IPVERSION; packet->ihl = sizeof (struct iphdr) / sizeof (int); printf ("check%s ", kind == IPF_BLOCKING ? "blocking" : "forwarding"); show_parms (argv); printf ("\n"); proto_name = *argv++; protocol = get_protocol (proto_name, check_usage, kind); switch (protocol) { case IP_FW_F_TCP: packet->protocol = IPPROTO_TCP; break; case IP_FW_F_UDP: packet->protocol = IPPROTO_UDP; break; default: fprintf (stderr, "ipfirewall: can only check TCP or UDP packets\n"); break; } if (*argv == NULL) { fprintf (stderr, "ipfirewall: missing \"from\" from keyword\n"); exit (1); } if (strcmp (*argv, "from") == 0) { argv += 1; get_ipaddr (*argv++, (struct in_addr *) &packet->saddr, NULL, check_usage, kind); if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP) { get_ports (&argv, &((struct tcphdr *) (&packet[1]))->th_sport, 1, 1, check_usage, kind, proto_name); ((struct tcphdr *) (&packet[1]))->th_sport = htons ( ((struct tcphdr *) (&packet[1]))->th_sport ); } } else { fprintf (stderr, "ipfirewall: expected \"from\" keyword, got \"%s\"\n", *argv); exit (1); } if (*argv == NULL) { fprintf (stderr, "ipfirewal