Return to sysio.h CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / 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: #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: }