Annotation of embedaddon/bird2/sysdep/bsd/sysio.h, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD Internet Routing Daemon -- BSD Multicasting and Network Includes
! 3: *
! 4: * (c) 2004 Ondrej Filip <feela@network.cz>
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9: #include <net/if_dl.h>
! 10: #include <netinet/in_systm.h> // Workaround for some BSDs
! 11: #include <netinet/ip.h>
! 12: #include <sys/param.h>
! 13:
! 14:
! 15: #ifdef __FreeBSD__
! 16: /* Should be defined in sysdep/cf/bsd.h, but it is flavor-specific */
! 17: #define CONFIG_DONTROUTE_UNICAST
! 18: #endif
! 19:
! 20: #ifdef __NetBSD__
! 21:
! 22: #ifndef IP_RECVTTL
! 23: #define IP_RECVTTL 23
! 24: #endif
! 25:
! 26: #ifndef IP_MINTTL
! 27: #define IP_MINTTL 24
! 28: #endif
! 29:
! 30: #endif
! 31:
! 32: #ifdef __DragonFly__
! 33: #define TCP_MD5SIG TCP_SIGNATURE_ENABLE
! 34: #endif
! 35:
! 36:
! 37: #undef SA_LEN
! 38: #define SA_LEN(x) (x).sa.sa_len
! 39:
! 40:
! 41: /*
! 42: * BSD IPv4 multicast syscalls
! 43: */
! 44:
! 45: #define INIT_MREQ4(maddr,ifa) \
! 46: { .imr_multiaddr = ipa_to_in4(maddr), .imr_interface = ip4_to_in4(ifa->sysdep) }
! 47:
! 48: static inline int
! 49: sk_setup_multicast4(sock *s)
! 50: {
! 51: struct in_addr ifa = ip4_to_in4(s->iface->sysdep);
! 52: u8 ttl = s->ttl;
! 53: u8 n = 0;
! 54:
! 55: /* This defines where should we send _outgoing_ multicasts */
! 56: if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &ifa, sizeof(ifa)) < 0)
! 57: ERR("IP_MULTICAST_IF");
! 58:
! 59: if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
! 60: ERR("IP_MULTICAST_TTL");
! 61:
! 62: if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
! 63: ERR("IP_MULTICAST_LOOP");
! 64:
! 65: return 0;
! 66: }
! 67:
! 68: static inline int
! 69: sk_join_group4(sock *s, ip_addr maddr)
! 70: {
! 71: struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
! 72:
! 73: if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
! 74: ERR("IP_ADD_MEMBERSHIP");
! 75:
! 76: return 0;
! 77: }
! 78:
! 79: static inline int
! 80: sk_leave_group4(sock *s, ip_addr maddr)
! 81: {
! 82: struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
! 83:
! 84: if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
! 85: ERR("IP_ADD_MEMBERSHIP");
! 86:
! 87: return 0;
! 88: }
! 89:
! 90:
! 91: /*
! 92: * BSD IPv4 packet control messages
! 93: */
! 94:
! 95: /* It uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
! 96:
! 97: #define CMSG4_SPACE_PKTINFO (CMSG_SPACE(sizeof(struct in_addr)) + \
! 98: CMSG_SPACE(sizeof(struct sockaddr_dl)))
! 99: #define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(char))
! 100:
! 101: static inline int
! 102: sk_request_cmsg4_pktinfo(sock *s)
! 103: {
! 104: int y = 1;
! 105:
! 106: if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &y, sizeof(y)) < 0)
! 107: ERR("IP_RECVDSTADDR");
! 108:
! 109: if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &y, sizeof(y)) < 0)
! 110: ERR("IP_RECVIF");
! 111:
! 112: return 0;
! 113: }
! 114:
! 115: static inline int
! 116: sk_request_cmsg4_ttl(sock *s)
! 117: {
! 118: int y = 1;
! 119:
! 120: if (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
! 121: ERR("IP_RECVTTL");
! 122:
! 123: return 0;
! 124: }
! 125:
! 126: static inline void
! 127: sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
! 128: {
! 129: if (cm->cmsg_type == IP_RECVDSTADDR)
! 130: s->laddr = ipa_from_in4(* (struct in_addr *) CMSG_DATA(cm));
! 131:
! 132: if (cm->cmsg_type == IP_RECVIF)
! 133: s->lifindex = ((struct sockaddr_dl *) CMSG_DATA(cm))->sdl_index;
! 134: }
! 135:
! 136: static inline void
! 137: sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
! 138: {
! 139: if (cm->cmsg_type == IP_RECVTTL)
! 140: s->rcv_ttl = * (byte *) CMSG_DATA(cm);
! 141: }
! 142:
! 143: #ifdef IP_SENDSRCADDR
! 144: static inline void
! 145: sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
! 146: {
! 147: /* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
! 148:
! 149: struct cmsghdr *cm;
! 150: struct in_addr *sa;
! 151: int controllen = 0;
! 152:
! 153: msg->msg_control = cbuf;
! 154: msg->msg_controllen = cbuflen;
! 155:
! 156: cm = CMSG_FIRSTHDR(msg);
! 157: cm->cmsg_level = IPPROTO_IP;
! 158: cm->cmsg_type = IP_SENDSRCADDR;
! 159: cm->cmsg_len = CMSG_LEN(sizeof(*sa));
! 160: controllen += CMSG_SPACE(sizeof(*sa));
! 161:
! 162: sa = (struct in_addr *) CMSG_DATA(cm);
! 163: *sa = ipa_to_in4(s->saddr);
! 164:
! 165: msg->msg_controllen = controllen;
! 166: }
! 167: #else
! 168: static inline void
! 169: sk_prepare_cmsgs4(sock *s UNUSED, struct msghdr *msg UNUSED, void *cbuf UNUSED, size_t cbuflen UNUSED) { }
! 170: #endif
! 171:
! 172: static void UNUSED
! 173: sk_prepare_ip_header(sock *s, void *hdr, int dlen)
! 174: {
! 175: struct ip *ip = hdr;
! 176:
! 177: bzero(ip, 20);
! 178:
! 179: ip->ip_v = 4;
! 180: ip->ip_hl = 5;
! 181: ip->ip_tos = (s->tos < 0) ? 0 : s->tos;
! 182: ip->ip_len = 20 + dlen;
! 183: ip->ip_ttl = (s->ttl < 0) ? 64 : s->ttl;
! 184: ip->ip_p = s->dport;
! 185: ip->ip_src = ipa_to_in4(s->saddr);
! 186: ip->ip_dst = ipa_to_in4(s->daddr);
! 187:
! 188: #if (defined __OpenBSD__) || (defined __DragonFly__) || (defined __FreeBSD__ && (__FreeBSD_version >= 1100030))
! 189: /* Different BSDs have different expectations of ip_len endianity */
! 190: ip->ip_len = htons(ip->ip_len);
! 191: #endif
! 192: }
! 193:
! 194:
! 195: /*
! 196: * Miscellaneous BSD socket syscalls
! 197: */
! 198:
! 199: #ifndef TCP_KEYLEN_MAX
! 200: #define TCP_KEYLEN_MAX 80
! 201: #endif
! 202:
! 203: #ifndef TCP_SIG_SPI
! 204: #define TCP_SIG_SPI 0x1000
! 205: #endif
! 206:
! 207: #if defined(__FreeBSD__)
! 208: #define USE_MD5SIG_SETKEY
! 209: #include "sysdep/bsd/setkey.h"
! 210: #endif
! 211:
! 212: int
! 213: sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote UNUSED, struct iface *ifa UNUSED, char *passwd, int setkey UNUSED)
! 214: {
! 215: #ifdef USE_MD5SIG_SETKEY
! 216: if (setkey)
! 217: if (sk_set_md5_in_sasp_db(s, local, remote, ifa, passwd) < 0)
! 218: return -1;
! 219: #endif
! 220:
! 221: int enable = (passwd && *passwd) ? TCP_SIG_SPI : 0;
! 222: if (setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable)) < 0)
! 223: {
! 224: if (errno == ENOPROTOOPT)
! 225: ERR_MSG("Kernel does not support TCP MD5 signatures");
! 226: else
! 227: ERR("TCP_MD5SIG");
! 228: }
! 229:
! 230: return 0;
! 231: }
! 232:
! 233: static inline int
! 234: sk_set_min_ttl4(sock *s, int ttl)
! 235: {
! 236: if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
! 237: {
! 238: if (errno == ENOPROTOOPT)
! 239: ERR_MSG("Kernel does not support IPv4 TTL security");
! 240: else
! 241: ERR("IP_MINTTL");
! 242: }
! 243:
! 244: return 0;
! 245: }
! 246:
! 247: static inline int
! 248: sk_set_min_ttl6(sock *s, int ttl UNUSED)
! 249: {
! 250: ERR_MSG("Kernel does not support IPv6 TTL security");
! 251: }
! 252:
! 253: static inline int
! 254: sk_disable_mtu_disc4(sock *s UNUSED)
! 255: {
! 256: /* TODO: Set IP_DONTFRAG to 0 ? */
! 257: return 0;
! 258: }
! 259:
! 260: static inline int
! 261: sk_disable_mtu_disc6(sock *s UNUSED)
! 262: {
! 263: /* TODO: Set IPV6_DONTFRAG to 0 ? */
! 264: return 0;
! 265: }
! 266:
! 267: int sk_priority_control = -1;
! 268:
! 269: static inline int
! 270: sk_set_priority(sock *s, int prio UNUSED)
! 271: {
! 272: ERR_MSG("Socket priority not supported");
! 273: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>