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