Return to sysio.h CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / sysdep / linux |
1.1 ! misho 1: /* ! 2: * BIRD Internet Routing Daemon -- Linux Multicasting and Network Includes ! 3: * ! 4: * (c) 1998--2000 Martin Mares <mj@ucw.cz> ! 5: * ! 6: * Can be freely distributed and used under the terms of the GNU GPL. ! 7: */ ! 8: ! 9: ! 10: #ifndef HAVE_STRUCT_IP_MREQN ! 11: /* Several versions of glibc don't define this structure, so we have to do it ourselves */ ! 12: struct ip_mreqn ! 13: { ! 14: struct in_addr imr_multiaddr; /* IP multicast address of group */ ! 15: struct in_addr imr_address; /* local IP address of interface */ ! 16: int imr_ifindex; /* Interface index */ ! 17: }; ! 18: #endif ! 19: ! 20: #ifndef IP_MINTTL ! 21: #define IP_MINTTL 21 ! 22: #endif ! 23: ! 24: #ifndef IPV6_TCLASS ! 25: #define IPV6_TCLASS 67 ! 26: #endif ! 27: ! 28: #ifndef IPV6_MINHOPCOUNT ! 29: #define IPV6_MINHOPCOUNT 73 ! 30: #endif ! 31: ! 32: ! 33: #ifndef TCP_MD5SIG ! 34: ! 35: #define TCP_MD5SIG 14 ! 36: #define TCP_MD5SIG_MAXKEYLEN 80 ! 37: ! 38: struct tcp_md5sig { ! 39: struct sockaddr_storage tcpm_addr; /* address associated */ ! 40: u16 __tcpm_pad1; /* zero */ ! 41: u16 tcpm_keylen; /* key length */ ! 42: u32 __tcpm_pad2; /* zero */ ! 43: u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */ ! 44: }; ! 45: ! 46: #endif ! 47: ! 48: ! 49: /* Linux does not care if sa_len is larger than needed */ ! 50: #define SA_LEN(x) sizeof(sockaddr) ! 51: ! 52: ! 53: /* ! 54: * Linux IPv4 multicast syscalls ! 55: */ ! 56: ! 57: #define INIT_MREQ4(maddr,ifa) \ ! 58: { .imr_multiaddr = ipa_to_in4(maddr), .imr_ifindex = ifa->index } ! 59: ! 60: static inline int ! 61: sk_setup_multicast4(sock *s) ! 62: { ! 63: struct ip_mreqn mr = { .imr_ifindex = s->iface->index }; ! 64: int ttl = s->ttl; ! 65: int n = 0; ! 66: ! 67: /* This defines where should we send _outgoing_ multicasts */ ! 68: if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mr, sizeof(mr)) < 0) ! 69: ERR("IP_MULTICAST_IF"); ! 70: ! 71: if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) ! 72: ERR("IP_MULTICAST_TTL"); ! 73: ! 74: if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0) ! 75: ERR("IP_MULTICAST_LOOP"); ! 76: ! 77: return 0; ! 78: } ! 79: ! 80: static inline int ! 81: sk_join_group4(sock *s, ip_addr maddr) ! 82: { ! 83: struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface); ! 84: ! 85: if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0) ! 86: ERR("IP_ADD_MEMBERSHIP"); ! 87: ! 88: return 0; ! 89: } ! 90: ! 91: static inline int ! 92: sk_leave_group4(sock *s, ip_addr maddr) ! 93: { ! 94: struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface); ! 95: ! 96: if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0) ! 97: ERR("IP_DROP_MEMBERSHIP"); ! 98: ! 99: return 0; ! 100: } ! 101: ! 102: ! 103: /* ! 104: * Linux IPv4 packet control messages ! 105: */ ! 106: ! 107: /* Mostly similar to standardized IPv6 code */ ! 108: ! 109: #define CMSG4_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in_pktinfo)) ! 110: #define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(int)) ! 111: ! 112: static inline int ! 113: sk_request_cmsg4_pktinfo(sock *s) ! 114: { ! 115: int y = 1; ! 116: ! 117: if (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &y, sizeof(y)) < 0) ! 118: ERR("IP_PKTINFO"); ! 119: ! 120: return 0; ! 121: } ! 122: ! 123: static inline int ! 124: sk_request_cmsg4_ttl(sock *s) ! 125: { ! 126: int y = 1; ! 127: ! 128: if (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &y, sizeof(y)) < 0) ! 129: ERR("IP_RECVTTL"); ! 130: ! 131: return 0; ! 132: } ! 133: ! 134: static inline void ! 135: sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm) ! 136: { ! 137: if (cm->cmsg_type == IP_PKTINFO) ! 138: { ! 139: struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cm); ! 140: s->laddr = ipa_from_in4(pi->ipi_addr); ! 141: s->lifindex = pi->ipi_ifindex; ! 142: } ! 143: } ! 144: ! 145: static inline void ! 146: sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm) ! 147: { ! 148: if (cm->cmsg_type == IP_TTL) ! 149: s->rcv_ttl = * (int *) CMSG_DATA(cm); ! 150: } ! 151: ! 152: static inline void ! 153: sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) ! 154: { ! 155: struct cmsghdr *cm; ! 156: struct in_pktinfo *pi; ! 157: int controllen = 0; ! 158: ! 159: msg->msg_control = cbuf; ! 160: msg->msg_controllen = cbuflen; ! 161: ! 162: cm = CMSG_FIRSTHDR(msg); ! 163: cm->cmsg_level = SOL_IP; ! 164: cm->cmsg_type = IP_PKTINFO; ! 165: cm->cmsg_len = CMSG_LEN(sizeof(*pi)); ! 166: controllen += CMSG_SPACE(sizeof(*pi)); ! 167: ! 168: pi = (struct in_pktinfo *) CMSG_DATA(cm); ! 169: pi->ipi_ifindex = s->iface ? s->iface->index : 0; ! 170: pi->ipi_spec_dst = ipa_to_in4(s->saddr); ! 171: pi->ipi_addr = ipa_to_in4(IPA_NONE); ! 172: ! 173: msg->msg_controllen = controllen; ! 174: } ! 175: ! 176: ! 177: /* ! 178: * Miscellaneous Linux socket syscalls ! 179: */ ! 180: ! 181: int ! 182: sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, struct iface *ifa, char *passwd, int setkey UNUSED) ! 183: { ! 184: struct tcp_md5sig md5; ! 185: ! 186: memset(&md5, 0, sizeof(md5)); ! 187: sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, remote, ifa, 0); ! 188: ! 189: if (passwd) ! 190: { ! 191: int len = strlen(passwd); ! 192: ! 193: if (len > TCP_MD5SIG_MAXKEYLEN) ! 194: ERR_MSG("The password for TCP MD5 Signature is too long"); ! 195: ! 196: md5.tcpm_keylen = len; ! 197: memcpy(&md5.tcpm_key, passwd, len); ! 198: } ! 199: ! 200: if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0) ! 201: { ! 202: if (errno == ENOPROTOOPT) ! 203: ERR_MSG("Kernel does not support TCP MD5 signatures"); ! 204: else ! 205: ERR("TCP_MD5SIG"); ! 206: } ! 207: ! 208: return 0; ! 209: } ! 210: ! 211: static inline int ! 212: sk_set_min_ttl4(sock *s, int ttl) ! 213: { ! 214: if (setsockopt(s->fd, SOL_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0) ! 215: { ! 216: if (errno == ENOPROTOOPT) ! 217: ERR_MSG("Kernel does not support IPv4 TTL security"); ! 218: else ! 219: ERR("IP_MINTTL"); ! 220: } ! 221: ! 222: return 0; ! 223: } ! 224: ! 225: static inline int ! 226: sk_set_min_ttl6(sock *s, int ttl) ! 227: { ! 228: if (setsockopt(s->fd, SOL_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0) ! 229: { ! 230: if (errno == ENOPROTOOPT) ! 231: ERR_MSG("Kernel does not support IPv6 TTL security"); ! 232: else ! 233: ERR("IPV6_MINHOPCOUNT"); ! 234: } ! 235: ! 236: return 0; ! 237: } ! 238: ! 239: static inline int ! 240: sk_disable_mtu_disc4(sock *s) ! 241: { ! 242: int dont = IP_PMTUDISC_DONT; ! 243: ! 244: if (setsockopt(s->fd, SOL_IP, IP_MTU_DISCOVER, &dont, sizeof(dont)) < 0) ! 245: ERR("IP_MTU_DISCOVER"); ! 246: ! 247: return 0; ! 248: } ! 249: ! 250: static inline int ! 251: sk_disable_mtu_disc6(sock *s) ! 252: { ! 253: int dont = IPV6_PMTUDISC_DONT; ! 254: ! 255: if (setsockopt(s->fd, SOL_IPV6, IPV6_MTU_DISCOVER, &dont, sizeof(dont)) < 0) ! 256: ERR("IPV6_MTU_DISCOVER"); ! 257: ! 258: return 0; ! 259: } ! 260: ! 261: int sk_priority_control = 7; ! 262: ! 263: static inline int ! 264: sk_set_priority(sock *s, int prio) ! 265: { ! 266: if (setsockopt(s->fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0) ! 267: ERR("SO_PRIORITY"); ! 268: ! 269: return 0; ! 270: } ! 271: