recvfromflags.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #include "unp.h"
  2. ssize_t
  3. recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
  4. SA *sa, socklen_t *salenptr, void *dstaddrp)
  5. {
  6. struct msghdr msg;
  7. struct iovec iov[1];
  8. ssize_t n;
  9. #ifdef HAVE_MSGHDR_MSG_CONTROL
  10. #define CONTROL_LEN (sizeof(struct cmsghdr) + sizeof(struct in_addr))
  11. char control[CONTROL_LEN];
  12. msg.msg_control = control;
  13. msg.msg_controllen = sizeof(control);
  14. msg.msg_flags = 0;
  15. #else
  16. bzero(&msg, sizeof(msg)); /* make certain msg_accrightslen = 0 */
  17. #endif
  18. msg.msg_name = sa;
  19. msg.msg_namelen = *salenptr;
  20. iov[0].iov_base = ptr;
  21. iov[0].iov_len = nbytes;
  22. msg.msg_iov = iov;
  23. msg.msg_iovlen = 1;
  24. if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
  25. return(n);
  26. *salenptr = msg.msg_namelen; /* pass back results */
  27. #ifdef HAVE_MSGHDR_MSG_CONTROL
  28. *flagsp = msg.msg_flags; /* pass back results */
  29. /*
  30. * We need someway to indicate to the caller that nothing was
  31. * returned through dstaddrp (since all 32-bit values are valid
  32. * IP destination addresses). To avoid having to add yet another
  33. * pointer argument, we return MSG_CTRUNC (which unp.h always
  34. * defines, even if the implementation does not).
  35. */
  36. #ifdef IP_RECVDSTADDR
  37. if (dstaddrp && msg.msg_controllen > 0 &&
  38. (msg.msg_flags & MSG_CTRUNC) == 0) {
  39. struct cmsghdr *cmptr = CMSG_FIRSTHDR(&msg);
  40. if (cmptr->cmsg_len != CONTROL_LEN)
  41. err_quit("control length = %d", cmptr->cmsg_len);
  42. if (cmptr->cmsg_level != IPPROTO_IP)
  43. err_quit("control level != IPPROTO_IP");
  44. if (cmptr->cmsg_type != IP_RECVDSTADDR)
  45. err_quit("control type != IP_RECVDSTADDR");
  46. memcpy(dstaddrp, CMSG_DATA(cmptr), sizeof(struct in_addr));
  47. } else
  48. #endif
  49. *flagsp |= MSG_CTRUNC; /* dest IP addr not returned */
  50. #else
  51. *flagsp |= MSG_CTRUNC; /* dest IP addr not returned */
  52. #endif /* HAVE_MSGHDR_MSG_CONTROL */
  53. return(n);
  54. }
  55. ssize_t
  56. Recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
  57. SA *sa, socklen_t *salenptr, void *dstaddrp)
  58. {
  59. ssize_t n;
  60. n = recvfrom_flags(fd, ptr, nbytes, flagsp, sa, salenptr, dstaddrp);
  61. if (n < 0)
  62. err_quit("recvfrom_flags error");
  63. return(n);
  64. }