Выбрать главу

  1: /* netlookup.с */

  2:

  3: #include <netdb.h>

  4: #include <arpa/inet.h>

  5: #include <netinet/in.h>

  6: #include <stdio.h>

  7: #include <string.h>

  8: #include <stdlib.h>

  9:

 10: /* Вызывается, если во время обработки командной строки происходит ошибка;

 11:    отображает короткое сообщение для пользователя и завершается. */

 12: void usage(void) {

 13:  fprintf(stderr, "использование: netlookup [--stream] [--dgram] "

 14:   "[--ipv4] [--ipv6] [--name] [--udp]\n");

 15:  fprintf (stderr, " [--tcp] [--cfg] "

 16:   "[--service <служба>] [--host <имя_хоста>]\n");

 17:  exit(1);

 18: }

 19:

 20: int main(int argc, const char ** argv) {

 21:  struct addrinfo * addr, * result;

 22:  const char ** ptr;

 23:  int rc;

 24:  struct addrinfo hints;

 25:  const char * serviceName = NULL;

 26:  const char * hostName = NULL;

 27:

 28:  /* очищает структуру подсказок */

 29:  memset(&hints, 0, sizeof(hints));

 30:

 31:  /* анализирует аргументы командной строки, игнорируя argv[0]

 32:

 33:     Структура hints, параметры serviceName и hostName будут

 34:     заполнены на основе переданных аргументов. */

 35:  ptr = argv + 1;

 36:  while (*ptr && *ptr[0] == '-') {

 37:   if (!strcmp(*ptr, "--ipv4"))

 38:    hints.ai_family = PF_INET;

 39:   else if (!strcmp(*ptr, "--ipv6"))

 40:    hints.ai_family = PF_INET6;

 41:   else if (!strcmp(*ptr, "--stream"))

 42:    hints.ai_socktype = SOCK_STREAM;

 43:   else if (!strcmp(*ptr, "--dgram"))

 44:    hints.ai_socktype = SOCK_DGRAM;

 45:   else if (!strcmp(*ptr, "--name"))

 46:    hints.ai_flags |= AI_CANONNAME;

 47:   else if (!strcmp(*ptr, "--cfg"))

 48:    hints.ai_flags |= AI_ADDRCONFIG;

 49:   else if (!strcmp(*ptr, "--tcp")) {

 50:    hints.ai_protocol = IPPROTO_TCP;

 51:   } else if (!strcmp(*ptr, "--udp")) {

 52:    hints.ai_protocol = IPPROTO_UDP;

 53:   } else if (!strcmp(*ptr, "--host")) {

 54:    ptr++;

 55:    if (!*ptr) usage();

 56:    hostName = *ptr;

 57:   } else if (!strcmp(*ptr, "--service")) {

 58:    ptr++;

 59:    if (!*ptr) usage();

 60:    serviceName = *ptr;

 61:   } else

 62:    usage();

 63:

 64:   ptr++;

 65:  }

 66:

 67:  /* необходимы имена hostName, serviceName или оба */

 68:  if (!hostName && !serviceName)

 69:   usage();

 70:

 71:  if ((rc = getaddrinfo(hostName, serviceName, &hints,

 72:   &cresult))) {

 73:   fprintf(stderr, "сбой поиска службы: %s\n",

 74:    gai_strerror(rc));

 75:   return 1;

 76:  }

 77:

 78:  /* проходит по связному списку, отображая все результаты */

 79:  addr = result;

 80:  while (addr) {

 81:   switch (addr->ai_family) {

 82:   case PF_INETs: printf("IPv4");

 83:    break;

 84:   case PF_INET6: printf("IPv6");

 85:    break;

 86:   default: printf("(%d) addr->ai_family);

 87:    break;

 88:   }

 89:

 90:   switch (addr->ai_socktype) {

 91:   case SOCK_STREAM: printf("\tstream");

 92:    break;

 93:   case SOCK_DGRAM: printf("\tdgram");

 94:    break;

 95:   case SOCK_RAW: printf("\traw");

 96:    break;

 97:   default: printf("\t(%d)

 98:    addr->ai_socktype);

 99:    break;

100:   }

101:

102:   if (addr->ai_family == PF_INET ||

103:    addr->ai_family == PF_INET6)

104:    switch (addr->ai_protocol) {

105:    case IPPROTO_TCP: printf("\ttcp");

106:     break;

107:    case IPPROTO_UDP: printf("\tudp");

108:     break;

109:    case IPPROTO_RAW: printf("\traw");

110:     break;

111:    default: printf("\t(%d)

112:     addr->ai_protocol);

113:     break;

114:    }

115:   else

116:    printf("\t");

117:

118:   /* отобразить информацию и для IPv4-, и для IPv6-адресов */

119:

120:   if (addr->ai_family == PF_INET) {

121:    struct sockaddr_in * inetaddr = (void*)addr->ai_addr;

122:    char nameBuf[INET_ADDRSTRLEN];

123:

124:    if (serviceName)

125:     printf("\tпорт%d", ntohs(inetaddr->sin_port));

126:

127:    if (hostName)

128:     printf("\tхост%s",

129:      inet_ntop(AF_INET, &inetaddr->sin_addr,

130:       nameBuf, sizeof(nameBuf)));

131:   } else if (addr->ai_family == PF_INET6) {

132:    struct sockaddr_in6 * inetaddr =

133:     (void*)addr->ai_addr;

134:    char nameBuf[INET6_ADDRSTRLEN];

135:

136:    if (serviceName)

137:     printf("\tпорт%d", ntohs(inetaddr->sin6_port));

138:

139:    if (hostName)

140:     printf("\tхост%s",

141:      inet_ntop(AF_INET6, &inetaddr->sin6_addr,

142:       nameBuf, sizeof(nameBuf)));

143:   }

144:

145:   if (addr->ai_canonname)