recvfromflags.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* include recvfrom_flags1 */
  2. #include "unp.h"
  3. #include <sys/param.h> /* ALIGN macro for CMSG_NXTHDR() macro */
  4. ssize_t
  5. recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
  6. SA *sa, socklen_t *salenptr, struct unp_in_pktinfo *pktp)
  7. {
  8. struct msghdr msg;
  9. struct iovec iov[1];
  10. ssize_t n;
  11. #ifdef HAVE_MSGHDR_MSG_CONTROL
  12. struct cmsghdr *cmptr;
  13. union {
  14. struct cmsghdr cm;
  15. char control[CMSG_SPACE(sizeof(struct in_addr)) +
  16. CMSG_SPACE(sizeof(struct unp_in_pktinfo))];
  17. } control_un;
  18. msg.msg_control = control_un.control;
  19. msg.msg_controllen = sizeof(control_un.control);
  20. msg.msg_flags = 0;
  21. #else
  22. bzero(&msg, sizeof(msg)); /* make certain msg_accrightslen = 0 */
  23. #endif
  24. msg.msg_name = sa;
  25. msg.msg_namelen = *salenptr;
  26. iov[0].iov_base = ptr;
  27. iov[0].iov_len = nbytes;
  28. msg.msg_iov = iov;
  29. msg.msg_iovlen = 1;
  30. if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
  31. return(n);
  32. *salenptr = msg.msg_namelen; /* pass back results */
  33. if (pktp)
  34. bzero(pktp, sizeof(struct unp_in_pktinfo)); /* 0.0.0.0, i/f = 0 */
  35. /* end recvfrom_flags1 */
  36. /* include recvfrom_flags2 */
  37. #ifndef HAVE_MSGHDR_MSG_CONTROL
  38. *flagsp = 0; /* pass back results */
  39. return(n);
  40. #else
  41. *flagsp = msg.msg_flags; /* pass back results */
  42. if (msg.msg_controllen < sizeof(struct cmsghdr) ||
  43. (msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
  44. return(n);
  45. for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
  46. cmptr = CMSG_NXTHDR(&msg, cmptr)) {
  47. #ifdef IP_RECVDSTADDR
  48. if (cmptr->cmsg_level == IPPROTO_IP &&
  49. cmptr->cmsg_type == IP_RECVDSTADDR) {
  50. memcpy(&pktp->ipi_addr, CMSG_DATA(cmptr),
  51. sizeof(struct in_addr));
  52. continue;
  53. }
  54. #endif
  55. #ifdef IP_RECVIF
  56. if (cmptr->cmsg_level == IPPROTO_IP &&
  57. cmptr->cmsg_type == IP_RECVIF) {
  58. struct sockaddr_dl *sdl;
  59. sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
  60. pktp->ipi_ifindex = sdl->sdl_index;
  61. continue;
  62. }
  63. #endif
  64. err_quit("unknown ancillary data, len = %d, level = %d, type = %d",
  65. cmptr->cmsg_len, cmptr->cmsg_level, cmptr->cmsg_type);
  66. }
  67. return(n);
  68. #endif /* HAVE_MSGHDR_MSG_CONTROL */
  69. }
  70. /* end recvfrom_flags2 */
  71. ssize_t
  72. Recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
  73. SA *sa, socklen_t *salenptr, struct unp_in_pktinfo *pktp)
  74. {
  75. ssize_t n;
  76. n = recvfrom_flags(fd, ptr, nbytes, flagsp, sa, salenptr, pktp);
  77. if (n < 0)
  78. err_quit("recvfrom_flags error");
  79. return(n);
  80. }