* Like strtol, but also translates service names into port numbers * for some protocols. * In particular: * proto == -1 disables the protocol check; * proto == IPPROTO_ETHERTYPE looks up an internal table * proto == matches the values there. * Returns *end == s in case the parameter is not found. */
| 944 | * Returns *end == s in case the parameter is not found. |
| 945 | */ |
| 946 | static int |
| 947 | strtoport(char *s, char **end, int base, int proto) |
| 948 | { |
| 949 | char *p, *buf; |
| 950 | char *s1; |
| 951 | int i; |
| 952 | |
| 953 | *end = s; /* default - not found */ |
| 954 | if (*s == '\0') |
| 955 | return 0; /* not found */ |
| 956 | |
| 957 | if (isdigit(*s)) |
| 958 | return strtol(s, end, base); |
| 959 | |
| 960 | /* |
| 961 | * find separator. '\\' escapes the next char. |
| 962 | */ |
| 963 | for (s1 = s; *s1 && (isalnum(*s1) || *s1 == '\\' || |
| 964 | *s1 == '_' || *s1 == '.') ; s1++) |
| 965 | if (*s1 == '\\' && s1[1] != '\0') |
| 966 | s1++; |
| 967 | |
| 968 | buf = safe_calloc(s1 - s + 1, 1); |
| 969 | |
| 970 | /* |
| 971 | * copy into a buffer skipping backslashes |
| 972 | */ |
| 973 | for (p = s, i = 0; p != s1 ; p++) |
| 974 | if (*p != '\\') |
| 975 | buf[i++] = *p; |
| 976 | buf[i++] = '\0'; |
| 977 | |
| 978 | if (proto == IPPROTO_ETHERTYPE) { |
| 979 | i = match_token(ether_types, buf); |
| 980 | free(buf); |
| 981 | if (i != -1) { /* found */ |
| 982 | *end = s1; |
| 983 | return i; |
| 984 | } |
| 985 | } else { |
| 986 | struct protoent *pe = NULL; |
| 987 | struct servent *se; |
| 988 | |
| 989 | if (proto != 0) |
| 990 | pe = getprotobynumber(proto); |
| 991 | setservent(1); |
| 992 | se = getservbyname(buf, pe ? pe->p_name : NULL); |
| 993 | free(buf); |
| 994 | if (se != NULL) { |
| 995 | *end = s1; |
| 996 | return ntohs(se->s_port); |
| 997 | } |
| 998 | } |
| 999 | return 0; /* not found */ |
| 1000 | } |
| 1001 | |
| 1002 | /* |
| 1003 | * Fill the body of the command with the list of port ranges. |
no test coverage detected