boot-it.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netdb.h>
  10. #include "bootp.h"
  11. static void usage(int argc, char **argv)
  12. {
  13. const char *name = argc ? argv[0] : "boot-it";
  14. printf("usage: %s [-H <bind to this host>] [-P <bind to this port>]\n",
  15. name);
  16. exit(EXIT_FAILURE);
  17. }
  18. int main(int argc, char **argv)
  19. {
  20. int c;
  21. int errct = 0;
  22. const char *bind_host = NULL;
  23. const char *bind_port = BOOTP_SERVER_PORT;
  24. while ((c = getopt(argc, argv, ":H:p:h")) != -1) {
  25. switch (c) {
  26. case 'H':
  27. bind_host = optarg;
  28. break;
  29. case 'p':
  30. bind_port = optarg;
  31. break;
  32. case ':':
  33. fprintf(stderr, "option -%c requries an operand\n", optopt);
  34. errct++;
  35. break;
  36. case '?':
  37. fprintf(stderr, "unrecognized option -%c\n", optopt);
  38. errct++;
  39. break;
  40. case 'h':
  41. usage(argc, argv);
  42. }
  43. }
  44. if (errct)
  45. usage(argc, argv);
  46. struct addrinfo hint = {
  47. .ai_family = AF_INET,
  48. .ai_socktype = SOCK_DGRAM,
  49. .ai_flags = AI_PASSIVE,
  50. };
  51. struct addrinfo *res;
  52. int s = getaddrinfo(bind_host, bind_port, &hint, &res);
  53. if (s != 0) {
  54. fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
  55. exit(EXIT_FAILURE);
  56. }
  57. int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  58. if (sock == -1) {
  59. fprintf(stderr, "could get socket: %s\n", strerror(errno));
  60. return 1;
  61. }
  62. s = bind(sock, res->ai_addr, res->ai_addrlen);
  63. if (!s) {
  64. fprintf(stderr, "bind failed: %s\n", strerror(errno));
  65. return 1;
  66. }
  67. freeaddrinfo(res);
  68. for (;;) {
  69. struct sockaddr_storage peer_addr;
  70. socklen_t peer_addr_len = sizeof(peer_addr);
  71. char buf[512];
  72. ssize_t nread = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&peer_addr, &peer_addr_len);
  73. if (nread == -1)
  74. continue;
  75. char host[NI_MAXHOST], service[NI_MAXSERV];
  76. s = getnameinfo((struct sockaddr *)&peer_addr,
  77. peer_addr_len, host, NI_MAXHOST,
  78. service, NI_MAXSERV, NI_NUMERICSERV|NI_NUMERICHOST);
  79. if (!s) {
  80. fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s));
  81. strncpy(host, "(unknown host)", sizeof(host));
  82. strncpy(service, "(unknown service)", sizeof(service));
  83. }
  84. printf("recv %zd bytes from %s:%s\n", nread, host, service);
  85. }
  86. return 0;
  87. }