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